0

I'm trying to combine my cpu soft renderer with imgui. Before that I manage to render using SDL_UpdateWindowSurface by updating the pixels of the windowSurface. The code goes lie this:

void WindowApp::updateCanvas(uint8_t* pixels, int width, int height, int channel) {
        SDL_LockSurface(windowSurface);
        Uint32* surfacePixels = (Uint32*)windowSurface->pixels;
        for(int i=0;i<height;i++){
            for(int j=0;j<width;j++){
                int index = i*width + j;
                Uint32 _color = SDL_MapRGB(
                        windowSurface->format,
                        pixels[index * channel + 0],
                        pixels[index * channel + 1],
                        pixels[index * channel + 2]);
                surfacePixels[index] = _color;
            }
        }
        SDL_UnlockSurface(windowSurface);
        SDL_UpdateWindowSurface(window);
    }

I notice that imgui uses SDL_GL_SwapWindow to render the UI, but when I put these two functions together, It will only render the original result instead of the UI. It will render the UI when I delete the SDL_UpdateWindowSurface function. So how can I manage to render the imgui UI on top of my original result? The wrong code goes like this:

void WindowApp::updateCanvas(uint8_t* pixels, int width, int height, int channel) {
        // Start the Dear ImGui frame
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplSDL2_NewFrame();
        ImGui::NewFrame();

        static float f = 0.0f;
        static int counter = 0;

        ImGui::Begin("Hello, world!");                          // Create a window called "Hello, world!" and append into it.

        ImGui::Text("This is some useful text.");               // Display some text (you can use a format strings too)

        ImGui::SliderFloat("float", &f, 0.0f, 1.0f);            // Edit 1 float using a slider from 0.0f to 1.0f
        if (ImGui::Button("Button"))                            // Buttons return true when clicked (most widgets return true when edited/activated)
            counter++;
        ImGui::SameLine();
        ImGui::Text("counter = %d", counter);

        ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
        ImGui::End();
        //SDL_LockSurface(windowSurface);
        Uint32* surfacePixels = (Uint32*)windowSurface->pixels;
        for(int i=0;i<height;i++){
            for(int j=0;j<width;j++){
                int index = i*width + j;
                Uint32 _color = SDL_MapRGB(
                        windowSurface->format,
                        pixels[index * channel + 0],
                        pixels[index * channel + 1],
                        pixels[index * channel + 2]);
                surfacePixels[index] = _color;
            }
        }

        //SDL_UnlockSurface(windowSurface);
        ImGui::Render();
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
        SDL_UpdateWindowSurface(window);
        SDL_GL_SwapWindow(window);
    }
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
assskiller
  • 21
  • 4
  • 2
    https://wiki.libsdl.org/SDL_GetWindowSurface "You may not combine this with 3D or the rendering API on this window.". So no, you can't. Your least difficult option is to push your surface contents to streaming texture and display it. – keltar Sep 15 '22 at 08:48
  • Or implement an ImGui backend on top of your software renderer, which is harder but is more interesting. – HolyBlackCat Sep 15 '22 at 17:01

0 Answers0