gpt4 book ai didi

c++ - SDL2 渲染到纹理

转载 作者:行者123 更新时间:2023-11-28 06:49:02 28 4
gpt4 key购买 nike

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

我也试过锁定每个 View 纹理的像素,试图手动复制像素,但锁定像素失败,除非纹理被创建为流纹理......而且, View 是不同的大小,因此需要将目标纹理向下拉伸(stretch)以适合,从而导致不必要的工作。

这导致我使用了 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) .充其量,这似乎会导致正确呈现的主视图(“源 View ”),但目标 View 却是一片漆黑。我觉得此时我已经尝试了一切,除非有超出我已经尝试过的东西……有什么想法吗?

最佳答案

我已经有点使用有点慢的——(但仍然比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 或等价物。但现在,我会将其标记为答案,直到有人可以提供更好的解决方案。

关于c++ - SDL2 渲染到纹理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24376704/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com