簡體   English   中英

SDL2渲染到紋理

[英]SDL2 Rendering to texture

我的應用程序具有多個視圖,這些視圖利用自己的SDL_WindowSDL_Renderer ,使用渲染器將我的所有圖塊層繪制到主視圖中(主視圖包含渲染多個圖塊層的合成結果,而其他視圖旨在顯示Photoshop樣式的“圖層面板”中的每個單獨圖層)。 這里的問題是嘗試獲取紋理(或表面,渲染器等)並將其渲染到另一個獨立視圖。 如果我使用SetRenderTargetSDL_RenderCopy ,它將失敗,因為目標紋理屬於其他渲染器...

我還嘗試過鎖定每個視圖紋理的像素,以嘗試手動復制像素,但是除非將紋理創建為流紋理,否則鎖定像素將失敗...而且,視圖的大小不同,因此目標紋理將需要向下拉伸以適合,從而導致所需工作量過多。

這使我使用SDL_SoftStretch ...這工作,但當然是痛苦的緩慢,因為它無法與硬件加速紋理使用。

是否有任何可行的,合理有效的方法來將一個SDL_Window的渲染輸出SDL_Window另一個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)。 充其量,這似乎會導致正確渲染的主視圖(“源視圖”),但呈現出深黑色的目標視圖。 我覺得我現在已經嘗試了所有方法,除非除了我已經嘗試過的東西以外,還有什么想法?

我已經使用速度較慢的方法(但仍然比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)配對時m_sdlSurface = SDL_GetWindowSurface(m_sdlWindow)很好

但是請注意,這並不能幫助縮小圖像,這可能意味着在將最終圖像提供給目的地之前,我仍然需要在某個時候使用RenderCopyEx或同等功能。 但就目前而言,我將其標記為答案,直到有人可以提供更好的解決方案為止。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM