int main()
{
// initialize opengl context
// sponza scene
std::shared_ptr<svo::Scene> scene = std::make_shared<svo::Scene>();
scene->LoadScene(SCENE_PATH);
scene->Initialize();
// a test octree structure, octree value is brick index
std::vector<uint32_t> octrees;
octrees.resize(octreeSize);
for (uint32_t i = 0; i < octreeSize; ++i) // octreeSize = 256u * 256u * 256u;
{
octrees[i] = i;
}
// a octree index texture, value of the pixel is the index of octree structure
GLuint neighborTex;
glCreateTextures(GL_TEXTURE_3D, 1, &neighborTex);
glTextureStorage3D(neighborTex, 8, GL_R32UI, octreeLen, octreeLen, octreeLen);
SET_SCALE_PARAM(neighborTex, GL_NEAREST, GL_NEAREST);
SET_WRAP_PARAM(neighborTex, GL_REPEAT);
// octree brick, brick size is 2 * 2 * 2,
GLuint blockTex;
glCreateTextures(GL_TEXTURE_3D, 1, &blockTex);
glTextureStorage3D(blockTex, 1, GL_R32UI, octreeLen * 2, octreeLen * 2, octreeLen * 2);
// octreeLen = 256u;
SET_SCALE_PARAM(blockTex, GL_LINEAR, GL_LINEAR);
SET_WRAP_PARAM(blockTex, GL_REPEAT);
//init neighborTex value
// init shader
GLuint initNeighborShader = glCreateProgram();
{
GLuint id = CreateShader("F:/VisualStudioProjects/svo_renderer/shader/test_large_texture/init_neighbor_tex.comp", GL_COMPUTE_SHADER);
glAttachShader(initNeighborShader, id);
glLinkProgram(initNeighborShader);
CheckCompileErrors(initNeighborShader, "PROGRAM");
glDeleteShader(id);
}
GLuint initBrickBlockShader = glCreateProgram();
{
GLuint id = CreateShader("F:/VisualStudioProjects/svo_renderer/shader/test_large_texture/init_brick_block_tex.comp", GL_COMPUTE_SHADER);
glAttachShader(initBrickBlockShader, id);
glLinkProgram(initBrickBlockShader);
CheckCompileErrors(initBrickBlockShader, "PROGRAM");
glDeleteShader(id);
}
GLuint sceneRender = glCreateProgram();
{
GLuint vShader = CreateShader("F:/VisualStudioProjects/svo_renderer/shader/test_large_texture/basic_scene_render.vert", GL_VERTEX_SHADER);
GLuint fShader = CreateShader("F:/VisualStudioProjects/svo_renderer/shader/test_large_texture/basic_scene_render.frag", GL_FRAGMENT_SHADER);
glAttachShader(sceneRender, vShader);
glAttachShader(sceneRender, fShader);
glLinkProgram(sceneRender);
CheckCompileErrors(sceneRender, "PROGRAM");
glDeleteShader(vShader);
glDeleteShader(fShader);
}
// init buffer object
GLuint octreeBO, neighborBO, brickPoolBO, contextBO, cameraContextBO;
glCreateBuffers(1, &octreeBO);
glNamedBufferStorage(octreeBO, sizeof(uint32_t) * octrees.size(), octrees.data(), 0);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, octreeBO);
glCreateBuffers(1, &neighborBO);
{
GLuint64 handle = glGetImageHandleARB(neighborTex, 0, GL_FALSE, 0, GL_R32UI);
glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
glNamedBufferStorage(neighborBO, sizeof(GLuint64), &handle, 0);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, neighborBO);
}
glCreateBuffers(1, &brickPoolBO);
{
GLuint64 handle = glGetImageHandleARB(blockTex, 0, GL_FALSE, 0, GL_R32UI);
glMakeImageHandleResidentARB(handle, GL_READ_WRITE);
glNamedBufferStorage(brickPoolBO, sizeof(GLuint64), &handle, 0);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, brickPoolBO);
}
glCreateBuffers(1, &contextBO);
{
std::vector<uint32_t> data = { octreeSize, octreeLen };
glNamedBufferStorage(contextBO, sizeof(uint32_t) * data.size(), data.data(), GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, contextBO);
}
glCreateBuffers(1, &cameraContextBO);
glNamedBufferStorage(cameraContextBO, sizeof(CameraContext), nullptr, GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT);
glBindBufferBase(GL_UNIFORM_BUFFER, 0, cameraContextBO);
{
CameraContext* data = (CameraContext*)glMapNamedBufferRange(cameraContextBO, 0, sizeof(CameraContext), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
data->model = glm::scale(mat4(1.0f), vec3(512.f));
glFlushMappedNamedBufferRange(cameraContextBO, 0, sizeof(CameraContext));
glUnmapNamedBuffer(cameraContextBO);
}
// start init 3d texture value
uint32_t groupX = GetGroupNum64(octreeSize);
glUseProgram(initNeighborShader);
glDispatchCompute(groupX, 1u, 1u);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
uint32_t num = octreeSize * 3;
{
uint32_t* data = (uint32_t*)glMapNamedBufferRange(contextBO, 0, sizeof(GLuint), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
*data = num;
glFlushMappedNamedBufferRange(contextBO, 0, sizeof(GLuint));
glUnmapNamedBuffer(contextBO);
}
groupX = GetGroupNum64(num);
glUseProgram(initBrickBlockShader);
glDispatchCompute(groupX, 1u, 1u);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0, 0, scr_width, scr_height);
glEnable(GL_DEPTH_TEST);
float accuTime = 0.f;
while (!glfwWindowShouldClose(window))
{
float currentFrame = glfwGetTime();
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
accuTime += deltaTime;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
// input
// -----
processInput(window);
{
CameraContext* data = (CameraContext*)glMapNamedBufferRange(cameraContextBO, 0, sizeof(CameraContext), GL_MAP_WRITE_BIT | GL_MAP_FLUSH_EXPLICIT_BIT);
data->view = camera->GetViewMatrix();
data->proj = glm::perspective(camera->GetCameraZoom(), 1.f, 0.1f, 100000.f);
glFlushMappedNamedBufferRange(cameraContextBO, 0, sizeof(CameraContext));
glUnmapNamedBuffer(cameraContextBO);
}
if (accuTime > 1.f)
{
auto eyeLoc = camera->GetCameraPos();
std::cout << "POS: " << eyeLoc.x << ", " << eyeLoc.y << ", " << eyeLoc.z << "\n";
auto forward = camera->GetCameraForward();
std::cout << "FORWARD: " << forward.x << ", " << forward.y << ", " << forward.z << "\n";
accuTime = 0.f;
}
glUseProgram(sceneRender);
scene->Draw();
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 0;
}
// init_neighbor_tex.comp, initialize neighborTex value
uint octreeInd = gl_GlobalInvocationID.x;
uint brickInd = octrees[octreeInd];
ivec3 brickCoord = GetBrickCoord(brickInd);
imageStore(neighbor, brickCoord, uvec4(brickInd));
// init_brick_block_tex.comp, use random value to initialize brick color
for (int x = 0; x < 2; ++x)
{
for (int y = 0; y < 2; ++y)
{
for (int z = 0; z < 2; ++z)
{
uint srcVal, curVal, dstVal = 0x00000000u;
ivec3 globalCoord = GetBrickCoord(brickInd, ivec3(x, y, z));
vec3 color = hashOld33(vec3(globalCoord + ivec3(x * 500, y * 400, z * 1000)));
color += vec3(1.0);
color /= 2.0;
uvec3 dstColor = uvec3(color * 256.0);
do
{
srcVal = curVal;
uvec4 srcColor = DecodeColorFromUint(srcVal);
srcColor = AccumulateColor(srcColor, dstColor);
dstVal = EncodeColorToUint(srcColor);
curVal = imageAtomicCompSwap(bricks, globalCoord, srcVal, dstVal);
} while (srcVal != curVal);
}
}
}
我正在使用稀疏体素八叉树,上面是测试代码。我使用两个大的 3d 纹理(256 * 256 * 256 和 512 * 512 * 512)来存储八叉树节点邻域信息和砖值。该演示工作正常,但是当我使用 Nsight 调试测试代码时,Nsight 无法捕获两个无绑定图像,我只能在 Nsight 配置文件窗口中看到第一个纹理。
但是 Nsight 实际上捕获了这两个 ssbo 对象。 黄色的线是两个纹理句柄的 ssbo。
平台是
显卡:GTX 1070 Ti
Ram:16GB
CPU:ryzen 2600x
系统:windows 10 Build
19043
Compiler Env:vc-142
OpenGL Version:4.5
我想知道Nsight无法捕获所有无绑定纹理的原因,有没有测试代码错误?