sdl2 opengl d3d9的mipmap和各项异性过滤渲染
Posted qianbo_insist
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sdl2 opengl d3d9的mipmap和各项异性过滤渲染相关的知识,希望对你有一定的参考价值。
sdl支持的驱动
列出后可以根据自己的需求去做,如果没有驱动就使用software去做就好了,以下列出对比,视频源为1280 720 的摄像头,使用RGB24来测试
opengl
CPU占用率在1.3% 到 1.5% 之间
GPU在5%到6.2%之间
D3D9
cpu 占用率在0.9 到1.6 之间
GPU在5%到6.2%之间
D3D11
CPU 占用率在0.7%到2.0% 之间
GPU在4.6%到5.7%之间
DEBUG 和RELEASE 并没有多大差异。
三者清晰度基本一致。
software
CPU 占用率在0.6%- 1.6%之间
GPU为零
测试代码
以下代码有冗余
int ret = cap.OpenCameraRGB(name.c_str(), w, h);
if (ret != 0)
return -1;
int screen_w, screen_h;
SDL_Window *screen = NULL;
SDL_Window *screenD3D = NULL;
SDL_Window *screenD3D11 = NULL;
SDL_Renderer *sdlRenderer = NULL;
SDL_Renderer *sdlRendererD3D = NULL;
SDL_Renderer *sdlRendererD3D11 = NULL;
SDL_Texture *sdlTexture = NULL;
SDL_Texture *sdlTextureD3D = NULL;
SDL_Texture *sdlTextureD3D11 = NULL;
SDL_Rect sdlRect;
SDL_Thread *video_tid;
SDL_Event event;
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
//SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4);
int MODE =-1;
screen_w = w;
screen_h = w *9 /16;
//screen_h = screen_w * 9 / 16;
if (MODE == -1)
screen = SDL_CreateWindow("FF", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
640, 360, SDL_WINDOW_SHOWN/* SDL_WINDOW_OPENGL*/); //,
else if(MODE == 0)
screenD3D = SDL_CreateWindow("FFD3D", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
640, 360, SDL_WINDOW_SHOWN/* SDL_WINDOW_OPENGL*/);
else if(MODE == 1)
screenD3D11 = SDL_CreateWindow("FFD3D11", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
640, 360, SDL_WINDOW_SHOWN/* SDL_WINDOW_OPENGL*/);
for (int i = 0; i < SDL_GetNumRenderDrivers(); ++i)
SDL_RendererInfo rendererInfo = ;
SDL_GetRenderDriverInfo(i, &rendererInfo);
cout <<i<<" "<< rendererInfo.name << endl;
//if (rendererInfo.name != std::string("direct3d11"))
//
// continue;
//
if (MODE == -1)
sdlRenderer = SDL_CreateRenderer(screen, 4, SDL_RENDERER_SOFTWARE);
sdlTexture = SDL_CreateTexture(sdlRenderer,
SDL_PIXELFORMAT_BGR24, //SDL_PIXELFORMAT_IYUV, //SDL_PIXELFORMAT_BGR24
SDL_TEXTUREACCESS_STREAMING,/*SDL_TEXTUREACCESS_STREAMING,*/
w, h);
else if (MODE == 0)
sdlRendererD3D = SDL_CreateRenderer(screenD3D, 0, SDL_RENDERER_ACCELERATED);
sdlTextureD3D = SDL_CreateTexture(sdlRendererD3D,
SDL_PIXELFORMAT_BGR24, //SDL_PIXELFORMAT_IYUV, //SDL_PIXELFORMAT_BGR24
SDL_TEXTUREACCESS_STREAMING,/*SDL_TEXTUREACCESS_STREAMING,*/
w, h);
else if (MODE == 1)
sdlRendererD3D11 = SDL_CreateRenderer(screenD3D11, 1, SDL_RENDERER_ACCELERATED);
sdlTextureD3D11 = SDL_CreateTexture(sdlRendererD3D11,
SDL_PIXELFORMAT_BGR24, //SDL_PIXELFORMAT_IYUV, //SDL_PIXELFORMAT_BGR24
SDL_TEXTUREACCESS_STREAMING,/*SDL_TEXTUREACCESS_STREAMING,*/
w, h);
sdlRect.x = 0;
sdlRect.y = 0;
sdlRect.w = w;
sdlRect.h = w*9/16;
video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, NULL);
int got_picture;
for (;;)
SDL_WaitEvent(&event);
if (event.type == SFM_REFRESH_EVENT)
uint8_t *frame = cap.QueryFrame();
if (frame != NULL)
//int y = screen_h * 2 / 3;
if (MODE == -1)
SDL_UpdateTexture(sdlTexture, NULL/*&sdlRect*/, frame, w * 3);
//SDL_UpdateTexture(sdlTexture, &sdlRect, out_buffer + W * H * 3, -W * 3);
SDL_RenderClear(sdlRenderer);
SDL_RenderCopy(sdlRenderer, sdlTexture, &sdlRect,NULL);
SDL_RenderPresent(sdlRenderer);
else if (MODE == 0)
SDL_UpdateTexture(sdlTextureD3D, NULL/*&sdlRect*/, frame, w * 3);
//SDL_UpdateTexture(sdlTexture, &sdlRect, out_buffer + W * H * 3, -W * 3);
SDL_RenderClear(sdlRendererD3D);
SDL_RenderCopy(sdlRendererD3D, sdlTextureD3D, &sdlRect, NULL);
SDL_RenderPresent(sdlRendererD3D);
else if (MODE == 1)
SDL_UpdateTexture(sdlTextureD3D11, NULL/*&sdlRect*/, frame, w * 3);
//SDL_UpdateTexture(sdlTexture, &sdlRect, out_buffer + W * H * 3, -W * 3);
SDL_RenderClear(sdlRendererD3D11);
SDL_RenderCopy(sdlRendererD3D11, sdlTextureD3D11, &sdlRect, NULL);
SDL_RenderPresent(sdlRendererD3D11);
else if (event.type == SDL_KEYDOWN)
if (event.key.keysym.sym == SDLK_SPACE)
thread_pause = !thread_pause;
else if (event.type == SDL_QUIT)
thread_exit = 1;
else if (event.type == SFM_BREAK_EVENT)
break;
sdl2 渲染问题
sdl2 的渲染里面并没有再高级的放大缩小算法,在大的图像缩小时会产生不舒服的纹理,需要滤波算法,这需要修改源码。
sdl opengl 渲染
screen = SDL_CreateWindow("FFGL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
640, 360, SDL_WINDOW_OPENGL); //,
glContext = SDL_GL_CreateContext(screen);
if (glContext == NULL)
// Display error message
printf("OpenGL context could not be created! SDL Error: %s\\n", SDL_GetError());
return false;
else
glewInit();
使用opengl 要创建opengl得窗口,并且产生mipmap图像,就能够比较清晰,这个要自己写的,sdl2 里面并没有加入这个方法,但是这个方式是可以的,需要自己写opengl的代码,下面使用d3d9,在sdl2 中d3d9也并没有使用mipmap 图像,也没有使用各项异性过滤。
修改sdl d3d9代码
/* setup default renderstate */
IDirect3DDevice9_SetRenderState(m_d3d_device, D3DRS_SRCBLEND, D3DBLEND_ONE);
IDirect3DDevice9_SetRenderState(m_d3d_device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
IDirect3DDevice9_SetRenderState(m_d3d_device, D3DRS_ALPHAFUNC, D3DCMP_GREATER);
IDirect3DDevice9_SetRenderState(m_d3d_device, D3DRS_ALPHAREF, (DWORD)0x0);
IDirect3DDevice9_SetRenderState(m_d3d_device, D3DRS_LIGHTING, FALSE);
IDirect3DDevice9_SetSamplerState(m_d3d_device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
IDirect3DDevice9_SetSamplerState(m_d3d_device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
找到所有Create_Texture 的代码
result = IDirect3DDevice9_CreateTexture(device, texturerep->w, texturerep->h,1, texturerep->usage,
PixelFormatToD3DFMT(texturerep->format), D3DPOOL_DEFAULT, &texturerep->texture, NULL);
修改成
result = IDirect3DDevice9_CreateTexture(device, texturerep->w, texturerep->h,0, texturerep->usage,
PixelFormatToD3DFMT(texturerep->format), D3DPOOL_DEFAULT, &texturerep->texture, NULL);
//1 改成0 ,
各项异性过滤加上,mipmap 生成等级map加上,结果出问题
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MINFILTER, D3DTEXF_ANISOTROPIC);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
IDirect3DDevice9_SetSamplerState(data->device, index, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
在d3d9 的render里面修改使用后,sdl 窗口大小必须和纹理大小一样,否则黑屏。所以这个方式就没有用了。
显示正确方法
前面得修改都去除,sdl 源代码不修改,如果直接使用ffmpeg的缩小方法,缩放到和窗口一样大小,那直接显示就非常好了。下面对比以下
总结
前面使用了一堆好的方法,sdl最后放到窗口上时没有算法保证过滤。这个要修正。
不使用sdl
不使用sdl,直接使用opengl 或者 direct3d是比较合适的。快速地做出一个显示效果可以使用sdl,不建议在产品中使用。
以上是关于sdl2 opengl d3d9的mipmap和各项异性过滤渲染的主要内容,如果未能解决你的问题,请参考以下文章
SDL2:如何同时拥有 SDL2 菜单和 OpenGL 上下文?