How can I create Direct3d 11 renderer using SDL 2.0.9

感情迁移 提交于 2020-02-02 12:47:45

问题


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:


  1. Enumerate the supported renderer backends via SDL_GetNumRenderDrivers() and SDL_GetRenderDriverInfo().
  2. Note the index of the direct3d11 driver, if it exists.
  3. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!