【发布时间】:2022-01-26 14:06:38
【问题描述】:
我在计算着色器中为 3D 纹理生成噪声,然后在 CPU 上构建网格。当我在主循环中这样做时效果很好,但我注意到我在第一次渲染时只填充了大约 1% 的噪声。这是一个最小的例子,我试图用着色器中的纹理填充 3D 纹理,但得到零或噪声作为回报:
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <stdlib.h>
void error(const char* message) { ... }
const char* slurp_file(const char* filename) { ... }
int main() {
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(100, 100, "", NULL, NULL);
glfwMakeContextCurrent(window);
gladLoadGL();
// create texture
GLuint texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_3D, texture);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
// allocate it
size_t size = 4;
glTexImage3D(GL_TEXTURE_3D, 0, GL_R32F, size, size, size, 0, GL_RED, GL_FLOAT, NULL);
// create shader
const char* shader_source = slurp_file("shaders/example.comp");
GLuint shader = glCreateShader(GL_COMPUTE_SHADER);
glShaderSource(shader, 1, &shader_source, NULL);
glCompileShader(shader);
// check it
int code;
glGetShaderiv(shader, GL_COMPILE_STATUS, &code);
if (!code) error("shader compilation failed");
// create program
int program = glCreateProgram();
glAttachShader(program, shader);
glLinkProgram(program);
// check it
glGetProgramiv(program, GL_LINK_STATUS, &code);
if (!code) error("program linkage failed");
// run shader
glUseProgram(program);
// i don't think it's needed, as 0 would be a default value
int uniform_loc = glGetUniformLocation(program, "img_output");
glUniform1i(uniform_loc, 0);
// dispatch and sync
glDispatchCompute(size, size, size);
// originally i had GL_TEXTURE_FETCH_BARRIER_BIT here
glMemoryBarrier(GL_ALL_BARRIER_BITS);
// read texture data
float* data = malloc(size * size * size * sizeof(float));
glBindImageTexture(0, texture, 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32F);
glGetTexImage(GL_TEXTURE_3D, 0, GL_RED, GL_FLOAT, data);
// prints 0s or noise, but i expect all 1s
for (int i = 0; i < size * size * size; i++)
printf("%f ", data[i]);
}
这是着色器:
#version 430
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
layout(binding = 0, r32f) writeonly uniform image3D img_output;
void main() {
ivec3 texture_coords = ivec3(gl_GlobalInvocationID.xyz);
vec4 pixel = vec4(1, 0, 0, 0);
imageStore(img_output, texture_coords, pixel);
}
在glDispatchCompute 之后添加睡眠什么都不做,所以我想我错过了一些锁定?或者也许应该以其他方式配置纹理?
【问题讨论】:
-
q1 为什么要将 vec4 写入仅红色通道图像? q2,您检查过您在 renderdoc 上的计算输出,您可以分享它们吗?
-
@Makogan imageStore 的数据始终是 vec4,即使纹理不是 RGBA。据我了解,如果无法存储值,则会忽略它们。不,我没有使用 renderdoc,可能是下一个着色器问题。
标签: opengl glsl textures memory-barriers