0

前段时间,我按照一些 SDL 教程对一些图像进行了 blit,并有一个测试函数循环遍历 SDL 纹理和目标反应的向量,然后调用以下函数将图像复制到窗口中。

void SpriteSheets::draw(const Sprite* sprite, SDL_Rect* dest) {
    SDL_RenderCopy(renderer, sprite->texture, sprite->rect, dest);
    SDL_RenderPresent(renderer);
}

// this is probably not relevant but including the clear/calling the draw function
void SpriteSheets::clearScreen() {
    SDL_SetRenderDrawColor(renderer, 150, 0, 100, 0); // debug color
    SDL_RenderClear(renderer);
}

void GameContext::drawSprites() {
    const auto& sprites  = std::get<comp::sprite>(c.components);
    const auto& position = std::get<comp::position>(c.components);

    SpriteSheets::clearScreen();

    for ( size_t i = 0; i < sprites.size(); i++ ) {
        SDL_Rect dest;
        dest.h = 50;
        dest.w = 50;
        dest.x = position[i].x();
        dest.y = position[i].y();
        SpriteSheets::draw(&sprites[i], &dest);
    }
}

这一切都“有效”,因为它可以很好地渲染所有“精灵”

然后我设置了很好的 imgui(我重写了大部分 sdl/vulkan 示例以使用 vulkan c++ 绑定而不是 c api)90% 的代码/结构来自 imgui 示例https://github.com/ocornut /imgui/blob/master/examples/example_sdl_vulkan/main.cpp 每个部分组织成单独的函数。

// relevant gui clear...
// at some point clear color is set to this
    this->clear_color = ImVec4(0.0f, 1.0f, 0.5f, 0.00f); //gross color for debugging
// snip
void Gui::clear(bool should_clear) {
    ImGui::Render();
    if ( should_clear ) memcpy(&wd.ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
}
// snip

void GraphicContext::mainLoop(GameContext* game) {
    //Frame Setup
    gui.frameSetup(); //rebuild swapchain if needed and then call imgui begin frame

    // draw the "game" 
    // which is just a few static png's at different locations
    game->drawSprites(); //when surounded by imgui functions it is hidden and not displayed

    //draw the imgui menu overtop
    if ( gui.show_demo_window ) ImGui::ShowDemoWindow(&gui.show_demo_window);

    //End frame
    gui.clear(false); // has ImGui::Render(); and conditional copy clear color 
    gui.frameRender(); // put all the imgui commands into a command buffer
    gui.framePresent(); // submit Queue
}

imgui 设置再次“起作用”,因为我成功显示了演示窗口。此外,我可以轻松制作自己的窗口,而且 API 没有问题。

我的问题是我只能让这两个概念分开工作。如果我删除清除屏幕/将清除值复制到 clear_color 背景颜色gui.clear(false);而不是gui.clear(true)imgui 清除颜色为黑色/它仍然覆盖 sdl 精灵。(与将清除值设置为 0 的 alpha 相同。)我尝试在 imgui 框架之前和之后订购“drawSprites”调用,但它总是覆盖它/覆盖它。

我意识到我没有包括一个最小的可重现示例,我没有包括所有的 imgui 函数,而是它的大量样板文件(vulkan 使设置/渲染/呈现函数超过 100 行,并且包括上下文的设置推动了另一个600 多行。)

有谁知道如何防止 imgui 清除屏幕(我已经在 sdl 部分清除屏幕)(可能更改渲染通道?)

//relevant part of frameRender()
{
    VkRenderPassBeginInfo info{
        .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
        .pNext = NULL,
        .renderPass = wd.RenderPass,
        .framebuffer = fd->Framebuffer,
        //.renderArea = {{0,0}, {wd.Width, wd.Height}},
        .clearValueCount = 1,
        .pClearValues = &wd.ClearValue
    };
    // the initializer for this doesn't work and idk why.
    // when I set the second two zeros in the render area initalizer list to width and height 
    // it wants to be converted to uint32 but when I do that it crashes with a read acess violation.
    info.renderArea.extent.width = wd.Width;
    info.renderArea.extent.height = wd.Height;

    vkCmdBeginRenderPass(fd->CommandBuffer, &info, VK_SUBPASS_CONTENTS_INLINE);
}

我尝试将清除值 count/pClearValue 设置为 NULL,但这只会使 info 结构不再有效/崩溃(必须至少有 1 个条目),并且我重新检查了此时清除颜色的 alpha 为 0。

或者,我可以尝试将所有 sdl 绘图合并到 imgui 命令缓冲区中(或者用纯 vulkan 替换 sdl 绘图)

我已经调试了好几个小时,慢慢地重写所有示例代码,以了解它的设置方式,但我处于与多年前完全相同的位置,在窗口的其余部分之上绘制几乎没有进展.

我可能不得不重做整个 Vulkan 教程,因为我接触它已经一年了,我的问题可能很明显,但我希望因为我使用 imgui 和 sdl,我可以先写一点引擎,然后再回到渲染后端如果需要,以后再优化东西。

4

0 回答 0