SDL2渲染到纹理

时间:2014-06-24 00:43:09

标签: c++ textures sdl sdl-2 render-to-texture

我的应用程序有多个视图,它们使用自己的SDL_WindowSDL_Renderer,使用渲染器将所有切片图层绘制到主视图中(主视图包含渲染多个图层的合成结果)瓦片,其他视图用于在photoshop风格的“图层”面板中显示每个单独的图层。这里的问题是尝试获取纹理(或表面,渲染器等)并将其渲染到另一个自包含的视图。如果我使用SetRenderTargetSDL_RenderCopy,则会失败,因为目标纹理属于不同的渲染器......

我还试图锁定每个视图纹理的像素,试图手动复制像素,但锁定像素会失败,除非纹理是作为流纹理创建的。 ,视图具有不同的大小,因此目标纹理需要向下拉伸以适应,从而导致更多的工作。

这导致我使用SDL_SoftStretch ...这有效,但当然痛苦慢,因为它不能与硬件加速纹理一起使用。

是否有任何合理有效的方法来获取一个SDL_Window的渲染输出,并将其缩小版本的版本渲染到另一个中?

<小时/>

修改
除了SDL_SoftStretch的狭窄使用,这是我最接近的事情...... 它失败是因为我在寻找从渲染器中获取像素数据的方法时碰到了另一个砖墙:

SDLView.cpp

//...
BOOL SDLView::Init()
{    
    m_sdlWindow = SDL_CreateWindowFrom( (PVOID)m_hWndParent );
    if(m_sdlWindow == NULL)
        return false;

    m_sdlRenderer = SDL_CreateRenderer(m_sdlWindow, -1, SDL_RendererFlags::SDL_RENDERER_ACCELERATED);
    if(m_sdlRenderer == NULL)
        return false;

    memset(&m_rect, 0, sizeof(SDL_Rect));
    SDL_GetRendererOutputSize(m_sdlRenderer, &m_rect.w, &m_rect.h);
    m_pixelFormat = SDL_GetWindowPixelFormat(m_sdlWindow);
    m_sdlTexture = SDL_CreateTexture(m_sdlRenderer, m_pixelFormat, SDL_TEXTUREACCESS_STREAMING, m_rect.w, m_rect.h);

    SDL_SetRenderDrawColor(m_sdlRenderer, 0x64, 0x95, 0xED, 0xFF);

    return true;
}

BOOL SDLView::Clear()
{
    memset(&m_rect, 0, sizeof(SDL_Rect));
    SDL_GetRendererOutputSize(m_sdlRenderer, &m_rect.w, &m_rect.h);
    return SDL_RenderClear(m_sdlRenderer) == 0;
}

VOID SDLView::Present()
{
    // Doesn't work because we still have no way of grabbing the rendered output!!
    SDL_RenderPresent(m_sdlRenderer);
    int result = SDL_RenderCopy(m_sdlRenderer, m_sdlTexture, NULL, NULL);
    if(result != 0) {
        std::string err(SDL_GetError());
        DebugBreak();
    }
}


LayerListItem.cpp

void CLayerListItem::OnPaint()
{
    CWnd::OnPaint();
    CRect rc;
    GetClientRect(&rc);

    if(m_destView != nullptr)
    {
        m_destView->Clear();
        if(m_srcView != nullptr)
        {
            int srcPitch = 0, destPitch = 0;
            void *srcPixels = nullptr, *destPixels = nullptr;

            // Lock the source pixels
            int ret = SDL_LockTexture(m_srcView->GetTexture(), &m_srcView->GetRect(), &srcPixels, &srcPitch);
            if(ret != 0) {
                std::string err(SDL_GetError());
                DebugBreak();
            }
            // Lock the destination pixels
            ret = SDL_LockTexture(m_destView->GetTexture(), &m_destView->GetRect(), &destPixels, &destPitch);
            if(ret != 0) {
                std::string err(SDL_GetError());
                DebugBreak();
            }

            // Unlock all pixels
            SDL_UnlockTexture(m_destView->GetTexture());
            SDL_UnlockTexture(m_srcView->GetTexture());

            // Update our destinaition texture
            // (I have tried every possible combination for this line, still no dice!)
            int result = SDL_UpdateTexture(
                m_destView->GetTexture(),
                &m_destView->GetRect(),
                srcPixels, srcPitch
            );
            if(ret != 0) {
                std::string err(SDL_GetError());
                DebugBreak();
            }
            SDL_RenderCopy(m_destView->GetRenderer(), m_destView->GetTexture(), NULL, NULL);

            OutputDebugStringA("[RENDERED!]...\n");
        }
        m_destView->Present();
    }
}



每隔几秒发送一次OnPaint事件,然后尝试抓取渲染的输出并将其存储在m_destView(与m_srcView一样,是SDLView)。最好,这似乎会产生正确渲染的主视图(源视图&#39;),但是黑色目标视图。我觉得我现在已经尝试了所有的东西,除非有超出我已经尝试过的东西......任何想法?

1 个答案:

答案 0 :(得分:1)

那种 使用稍慢的方式解决了这个问题 - (但仍然优于SDL_SoftRect) - 函数SDL_RenderReadPixels

VOID SDLView::CopyTo(SDLView *targetView)
{
    int result = SDL_RenderReadPixels(m_sdlRenderer, nullptr, m_pixelFormat, m_sdlSurface->pixels, m_sdlSurface->pitch);
    if(result != 0) {
        std::string err(SDL_GetError());
        OutputDebugStringA(err.c_str());
        return;
    }

    SDL_Texture *destTexture = targetView->GetTexture();
    result = SDL_UpdateTexture(destTexture, nullptr, m_sdlSurface->pixels, m_sdlSurface->pitch);
    if(result != 0) {
        std::string err(SDL_GetError());
        OutputDebugStringA(err.c_str());
        return;
    }
}


m_sdlSurface = SDL_GetWindowSurface(m_sdlWindow)以及m_pixelFormat = SDL_GetWindowPixelFormat(m_sdlWindow) ...

配对时效果很好

但请注意,这对缩小图像没有帮助,这可能意味着在将最终图像提供到目标之前,我仍然需要在某个时刻使用RenderCopyEx或等效图像。 但就目前而言,我会将此标记为答案,直到有人能够提供更好的解决方案。