问题
In my project I must use SDL_BLENDOPERATION_MAXIMUM
via SDL_ComposeCustomBlendMode()
which is supported in SDL 2.0.9 by direct3d11 renderer only. I have Windows 8.1 and GeForce GTX750 Ti with updated drivers. My system should support DirectX 11 renderending.
Changing defines in SDL_config.h
or SDL_config_windows.h
(SDL_VIDEO_RENDER_D3D11
to 1 and SDL_VIDEO_RENDER_D3D
to 0) doesn't help.
I tried to fill preprocessor difinitions with defines SDL_VIDEO_RENDER_D3D11 or WINRT according to SDL source code. But it doesn't help.
What should I do to activate direct3d11 renderer so I can use blend mode max?
My test code:
#include "SDL.h"
#include "SDL_image.h"
#include <string>
using namespace std;
int main( int argc, char *argv[] ) {
SDL_Init( SDL_INIT_VIDEO );
IMG_Init( IMG_INIT_PNG );
SDL_SetHintWithPriority( SDL_HINT_RENDER_DRIVER, "direct3d11", SDL_HINT_OVERRIDE );
SDL_Window *window = SDL_CreateWindow( "Testing", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
1200, 600, SDL_WINDOW_RESIZABLE );
SDL_Renderer *renderer = SDL_CreateRenderer( window, -1, SDL_RENDERER_ACCELERATED );
SDL_RendererInfo *rendererInfo = new SDL_RendererInfo();
SDL_RendererInfo *driverInfo = new SDL_RendererInfo();
SDL_GetRendererInfo( renderer, rendererInfo );
int drivers = SDL_GetNumRenderDrivers();
string availableDrivers = " (";
for ( int i = 0; i < drivers; ++i ) {
SDL_GetRenderDriverInfo( i, driverInfo );
string driverName = driverInfo->name;
if ( i == drivers - 1 ) {
availableDrivers += driverName;
}
else {
availableDrivers += driverName + ", ";
}
}
availableDrivers += ")";
string path = SDL_GetBasePath();
SDL_Surface *surfRed = IMG_Load( (path + "\\Red.png").c_str() );
SDL_Texture *textRed = SDL_CreateTextureFromSurface( renderer, surfRed );
SDL_FreeSurface( surfRed );
SDL_Surface *surfBlue = IMG_Load( ( path + "\\Blue.png" ).c_str() );
SDL_Texture *textBlue = SDL_CreateTextureFromSurface( renderer, surfBlue );
SDL_FreeSurface( surfBlue );
SDL_Rect destRed, destBlue;
destRed.x = 128;
destRed.y = 128;
destBlue.x = 196;
destBlue.y = 196;
SDL_QueryTexture( textRed, NULL, NULL, &destRed.w, &destRed.h );
SDL_QueryTexture( textBlue, NULL, NULL, &destBlue.w, &destBlue.h );
SDL_BlendMode blendMode = SDL_ComposeCustomBlendMode( SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_MAXIMUM,
SDL_BLENDFACTOR_ONE, SDL_BLENDFACTOR_ONE, SDL_BLENDOPERATION_MAXIMUM );
SDL_SetTextureBlendMode( textRed, blendMode );
SDL_SetTextureBlendMode( textBlue, blendMode );
// SDL_SetRenderDrawBlendMode( renderer, blendMode );
string info = rendererInfo->name + availableDrivers + " " + SDL_GetError();
SDL_SetWindowTitle( window, info.c_str() );
SDL_SetRenderDrawColor( renderer, 0, 0, 0, 255 );
SDL_Event event;
bool isRunning = true;
while ( isRunning ) {
if ( SDL_PollEvent( &event ) ) {
if ( event.type == SDL_QUIT ) {
isRunning = false;
}
}
SDL_RenderClear( renderer );
SDL_RenderCopy( renderer, textRed, NULL, &destRed );
SDL_RenderCopy( renderer, textBlue, NULL, &destBlue );
SDL_RenderPresent( renderer );
}
delete driverInfo;
delete rendererInfo;
SDL_DestroyTexture( textRed );
SDL_DestroyTexture( textBlue );
SDL_DestroyRenderer( renderer );
SDL_DestroyWindow( window );
IMG_Quit();
SDL_Quit();
return 0;
}
Window title is "direct3d (direct3d, opengl, opengles2, software) This operration is not supported". It works fine when I change to SDL_BLENDOPERATION_ADD, but it's not what I want. If I uncomment renderer blend mode it doesn't help too.
回答1:
- Enumerate the supported renderer backends via
SDL_GetNumRenderDrivers()
andSDL_GetRenderDriverInfo()
. - Note the index of the
direct3d11
driver, if it exists. - Pass index into
SDL_CreateRenderer()
.
All together:
SDL_Init( SDL_INIT_VIDEO );
SDL_Window* window = SDL_CreateWindow( "SDL2", 0, 0, 640, 480, SDL_WINDOW_SHOWN );
SDL_Renderer* renderer = nullptr;
for( int i = 0; i < SDL_GetNumRenderDrivers(); ++i )
{
SDL_RendererInfo rendererInfo = {};
SDL_GetRenderDriverInfo( i, &rendererInfo );
if( rendererInfo.name != std::string( "direct3d11" ) )
{
continue;
}
renderer = SDL_CreateRenderer( window, i, 0 );
break;
}
回答2:
Note that what you are setting with SDL_VIDEO_RENDER_D3D
and friends are compile time definitions for building SDL with D3D support.
To do this at runtime:
Sometime after SDL_Init()
and before creating your window/renderer set a hint for it.
// returns true on success or false on failure
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "direct3d11");
However, this will only work on Windows, and I believe d3d is already the default renderer for windows. If your version of windows supports d3d11 that is what SDL should use. I strongly suspect you already have a d3d11 renderer and your problem is with how you instantiate or use your custom blend mode.
To verify you have a d3d11 renderer:
SDL_RendererInfo info;
SDL_GetRendererInfo(renderer, &info);
printf("%s", info.name);
To create a custom blend mode with SDL_BLENDOPERATION_MAXIMUM
SDL_BlendMode blender = SDL_ComposeCustomBlendMode(SDL_BLENDFACTOR_SRC_ALPHA, // change this to suit your needs
SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, // change this to suit your needs
SDL_BLENDOPERATION_MAXIMUM,
SDL_BLENDFACTOR_ONE, // change this to suit your needs
SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, // change this to suit your needs
SDL_BLENDOPERATION_MAXIMUM);
SDL_SetTextureBlendMode(texture, blender); // blender is your custom mode
SDL_SetRenderDrawBlendMode(renderer, blender); // blender is your custom mode
I cant imagine the above blender is actually the combination of factors/operations you want, but you didn't post your actual code to work off.
来源:https://stackoverflow.com/questions/53269015/how-can-i-create-direct3d-11-renderer-using-sdl-2-0-9