计算着色器写入纹理

mik*_*ike 6 opengl glsl compute-shader map-projections

我已经实现了CPU代码,可以将投影纹理复制到3d对象上的更大纹理,如果愿意,可以"贴花烘焙",但现在我需要在GPU上实现它.为此,我希望使用计算着色器,因为在我当前的设置中添加FBO非常困难.

我当前实现的示例图像

这个问题更多的是关于如何使用Compute着色器,但对于任何感兴趣的人,这个想法是基于我从用户jozxyqk得到的答案,在这里看到:https://stackoverflow.com/a/27124029/2579996

写入的纹理在我的代码中被调用_texture,而投影的纹理是_textureProj

简单的计算着色器

const char *csSrc[] = {
    "#version 440\n",
    "layout (binding = 0, rgba32f) uniform image2D destTex;\
     layout (local_size_x = 16, local_size_y = 16) in;\
     void main() {\
           ivec2 storePos = ivec2(gl_GlobalInvocationID.xy);\
           imageStore(destTex, storePos, vec4(0.0,0.0,1.0,1.0));\
    }"
};
Run Code Online (Sandbox Code Playgroud)

如您所见,我目前只想将纹理更新为某种任意(蓝色)颜色.

更新功能

void updateTex(){ 
    glUseProgram(_computeShader);
    const GLint location = glGetUniformLocation(_computeShader, "destTex"); 
    if (location == -1){
        printf("Could not locate uniform location for texture in CS");
    }
    // bind texture
    glUniform1i(location, 0); 
    glBindImageTexture(0, *_texture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32F);
    // ^second param returns the GLint id - that im sure of. 

    glDispatchCompute(_texture->width() / 16, _texture->height() / 16, 1); 
    glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);

    glUseProgram(0);
    printOpenGLError(); // reports no errors.
}
Run Code Online (Sandbox Code Playgroud)

问题 如果我调用updateTex()我的主程序对象的外部我看到效果,而如果我在其范围内调用它,如下所示:

 glUseProgram(_id); // vert, frag shader pipe
  updateTex();
  // Pass uniforms to shader 
  // bind _textureProj & _texture (latter is the one im trying to update) 
 glUseProgram(0);
Run Code Online (Sandbox Code Playgroud)

然后在渲染时我看到了这个:

问题: 我意识到在主程序对象范围内设置更新方法不是正确的方法,但它是获得任何视觉结果的唯一方法.在我看来,发生的事情是,它几乎消除了碎片整理并吸引到屏幕空间......

我该怎么做才能让它正常工作?(我主要关注的是能够在纹理和更新中写任何东西)

如果需要发布更多代码,请告诉我.

joz*_*yqk 4

我相信在这种情况下,FBO会更容易、更快,并且会推荐这样做。但这个问题本身仍然很有效。

我很惊讶地看到一个球体,因为您正在将蓝色写入整个纹理(如果纹理大小不是 16 的倍数,则减去任何边缘位)。我猜这是来自其他地方的代码。

不管怎样,你的主要问题似乎是能够从常规渲染的设置代码之外的计算着色器写入纹理。我怀疑这与你如何绑定图像有关destTex。我不确定你的TexUnitactivate方法是做什么的,但是要将 GL 纹理绑定到图像单元,请执行以下操作:

int imageUnitIndex = 0; //something unique
int uniformLocation = glGetUniformLocation(...);
glUniform1i(uniformLocation, imageUnitIndex); //program must be active
glBindImageTexture(imageUnitIndex, textureHandle, ...);
Run Code Online (Sandbox Code Playgroud)

看:

最后,随着你的使用,使用的障碍image2D也随之而来。用于存储缓冲区对象GL_SHADER_IMAGE_ACCESS_BARRIER_BITGL_SHADER_STORAGE_BARRIER_BIT