Directx11:删除特定精灵的alpha混合

时间:2012-09-01 14:47:53

标签: c++ directx sprite alphablending dds-format

背景:   - 过去6周我一直在努力学习Directx 11编程。

我正在本书后面的屏幕上呈现dds图像 http://www.amazon.co.uk/Beginning-Directx-11-Game-Programming/dp/1435458958/ref=sr_1_1?ie=UTF8&qid=1346510304&sr=8-1

我试图在2D背景上绘制2D精灵,它本身也是2D精灵。问题是这两行

d3dDevice _-> CreateBlendState(& blendDesc,& alphaBlendState_);

d3dContext _-> OMSetBlendState(alphaBlendState_,blendFactor,0xFFFFFFFF);

在dds图像中启用Alpha透明度。我喜欢混合精灵,但现在每个精灵都与我的蓝色背景混合,从而产生蓝色标志,图标等。

如何让Alpha Blending忽略directx 11中的特定图像?

由于背景精灵是第一个被绘制的,所以当渲染其他精灵而没有每个精灵变成蓝色时,我无法在代码中激活混合。

提前感谢:)

编辑: 过去3周我一直在研究这个问题,但仍然没有解决方案。每次在DeviceContext中启用混合状态似乎都适用于屏幕上绘制的每个纹理,无论渲染顺序如何。

以下是头文件的源代码:

class GameSpriteDemo : public Dx11DemoBase
{
    public:
        GameSpriteDemo( );
        virtual ~GameSpriteDemo( );

        bool LoadContent( );
        void UnloadContent( );

        void Update( float dt );
        void Render( );

        void DisableBlending();
        ID3D11ShaderResourceView* getColorMap(int);
        int UniqSpriteAmount();

        // text rendering system
    private:
        bool DrawString( char* message, float startX, float startY );

    private:
        ID3D11VertexShader* solidColorVS_;
        ID3D11VertexShader* solidColorVS_2;

        ID3DX11Effect* effect_;

        vector<ID3D11VertexShader*> solidColorVShaders; 
        ID3D11PixelShader* solidColorPS_;
        ID3D11PixelShader* solidColorPS_2;

        ID3D11InputLayout* inputLayout_;
        ID3D11InputLayout* inputLayout2;
        ID3D11Buffer* vertexBuffer_;
        vector<ID3D11Buffer*> vertexBuffers;

        ID3D11ShaderResourceView* colorMap_;
        vector<ID3D11ShaderResourceView*> colorMaps;
        ID3D11SamplerState* colorMapSampler_;
        vector<ID3D11SamplerState*> colorSamplers;
        ID3D11BlendState* alphaBlendState_;
        ID3D11BlendState* alphaBlendStateOff;


        vector<LPCTSTR> elements2D;
        vector<GameSprite> sprites_;
        ID3D11Buffer* mvpCB_;
        XMMATRIX vpMatrix_;

};

#endif

以下是cpp文件的源代码:(不需要基类DxD11DemoClass,因为它只设置了SwapChain和D3DContext)

bool GameSpriteDemo::LoadContent( )
{
    // add sprite textures to the engine, giving them index 0, 1, 2... etc. 
    elements2D.push_back("placeholder3.dds");
    elements2D.push_back("cav.dds");
    elements2D.push_back("Stats.dds");

    // create sprites
        XMFLOAT2 sprite1Pos( 0.0f, 500.0f);
    GameSprite sprite1(getDevice(), "placeholder3.dds", 0, sprite1Pos, 0.0f);
            XMFLOAT2 sprite1Scale( 0.5f, 0.5f );
            XMFLOAT2 mini(0.8f, 0.6f);
    sprite1.SetScale(mini);
    sprites_.push_back(sprite1);

    XMFLOAT2 sprite2Pos( 200.0f, 100.0f );
    GameSprite sprite2(getDevice(), "Stats.dds", 2, sprite2Pos, 2.0f);
    // sprites_.push_back(sprite2);

    XMFLOAT2 sprite3Pos( 290.0f, 300.0f );
    GameSprite sprite3(getDevice(), "cav.dds", 1, sprite3Pos, 2.0f);
    sprite3.SetScale(sprite1Scale);
    sprites_.push_back(sprite3);

    // create vertex buffers, colorMaps and colorSamplers
    for (int i = 0; i <= elements2D.size(); i++) {
    solidColorVShaders.push_back(solidColorVS_);
    colorMaps.push_back(colorMap_);
    colorSamplers.push_back(colorMapSampler_);
    vertexBuffers.push_back(vertexBuffer_);
    }

    // continue 
    ID3DBlob* vsBuffer = 0;

    bool compileResult = CompileD3DShader( "TextureMap.fx", "VS_Main", "vs_4_0", &vsBuffer );

    if( compileResult == false )
    {
        DXTRACE_MSG( "Error compiling the vertex shader!" );
        return false;
    }

    HRESULT d3dResult;

    d3dResult = d3dDevice_->CreateVertexShader( vsBuffer->GetBufferPointer( ),
        vsBuffer->GetBufferSize( ), 0, &solidColorVShaders[0] );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Error creating the vertex shader!" );

        if( vsBuffer )
            vsBuffer->Release( );

        return false;
    }



    D3D11_INPUT_ELEMENT_DESC solidColorLayout[] =
    {
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
        { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
    };

    unsigned int totalLayoutElements = ARRAYSIZE( solidColorLayout );

    d3dResult = d3dDevice_->CreateInputLayout( solidColorLayout, totalLayoutElements,
        vsBuffer->GetBufferPointer( ), vsBuffer->GetBufferSize( ), &inputLayout_ );

    vsBuffer->Release( );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Error creating the input layout!" );
        return false;
    }

    ID3DBlob* psBuffer = 0;

    compileResult = CompileD3DShader( "TextureMap.fx", "PS_Main", "ps_4_0", &psBuffer );

    if( compileResult == false )
    {
        DXTRACE_MSG( "Error compiling pixel shader!" );
        return false;
    }

    d3dResult = d3dDevice_->CreatePixelShader( psBuffer->GetBufferPointer( ),
        psBuffer->GetBufferSize( ), 0, &solidColorPS_ );

    psBuffer->Release( );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Error creating pixel shader!" );
        return false;
    }

    // create ColorMap, ColorSampler and VertexBuffer for each unique sprite
    D3D11_SAMPLER_DESC colorMapDesc;
    D3D11_BUFFER_DESC vertexDesc;
    D3D11_SUBRESOURCE_DATA resourceData;

    for (int j = 0; j < elements2D.size(); j++) {

    d3dResult = D3DX11CreateShaderResourceViewFromFile( d3dDevice_,
        elements2D[j], 0, 0, &colorMaps[j], 0 );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Failed to load the texture image!" );
        return false;
    }

    ZeroMemory( &colorMapDesc, sizeof( colorMapDesc ) );
    colorMapDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    colorMapDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    colorMapDesc.MaxLOD = D3D11_FLOAT32_MAX;

    d3dResult = d3dDevice_->CreateSamplerState( &colorMapDesc, &colorSamplers[j] );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Failed to create color map sampler state!" );
        return false;
    }

    float Width = sprites_[j].getWidth();
    float Height = sprites_[j].getHeight();


    VertexPos vertices[] =
    {
        { XMFLOAT3(  Width,  Height, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
        { XMFLOAT3(  Width, -Height, 1.0f ), XMFLOAT2( 1.0f, 1.0f ) },
        { XMFLOAT3( -Width, -Height, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) },

        { XMFLOAT3( -Width, -Height, 1.0f ), XMFLOAT2( 0.0f, 1.0f ) },
        { XMFLOAT3( -Width,  Height, 1.0f ), XMFLOAT2( 0.0f, 0.0f ) },
        { XMFLOAT3(  Width,  Height, 1.0f ), XMFLOAT2( 1.0f, 0.0f ) },
    };

    ZeroMemory( &vertexDesc, sizeof( vertexDesc ) );
    vertexDesc.Usage = D3D11_USAGE_DEFAULT;
    vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    vertexDesc.ByteWidth = sizeof( VertexPos ) * 6;

    ZeroMemory( &resourceData, sizeof( resourceData ) );
    resourceData.pSysMem = vertices;

    d3dResult = d3dDevice_->CreateBuffer( &vertexDesc, &resourceData, &vertexBuffers[j] );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Failed to create vertex buffer!" );
        return false;
    }

    }
    // end of foor loop

    // create text fonts
        d3dResult = D3DX11CreateShaderResourceViewFromFile( d3dDevice_,
        "font.dds", 0, 0, &colorMap_, 0 );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Failed to load the texture image!" );
        return false;
    }

    D3D11_SAMPLER_DESC colorMapDesc2;
    ZeroMemory( &colorMapDesc2, sizeof( colorMapDesc2 ) );
    colorMapDesc2.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc2.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc2.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    colorMapDesc2.ComparisonFunc = D3D11_COMPARISON_NEVER;
    colorMapDesc2.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    colorMapDesc2.MaxLOD = D3D11_FLOAT32_MAX;

    d3dResult = d3dDevice_->CreateSamplerState( &colorMapDesc2, &colorMapSampler_ );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Failed to create color map sampler state!" );
        return false;
    }

    D3D11_BUFFER_DESC vertexDesc2;
    ZeroMemory( &vertexDesc2, sizeof( vertexDesc2 ) );
    vertexDesc2.Usage = D3D11_USAGE_DYNAMIC;
    vertexDesc2.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
    vertexDesc2.BindFlags = D3D11_BIND_VERTEX_BUFFER;

    const int sizeOfSprite = sizeof( VertexPos ) * 6;
    const int maxLetters = 24;

    vertexDesc2.ByteWidth = sizeOfSprite * maxLetters;

    d3dResult = d3dDevice_->CreateBuffer( &vertexDesc2, 0, &vertexBuffer_ );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Failed to create vertex buffer!" );
        return false;
    }

    // end of font creation

    D3D11_BUFFER_DESC constDesc;
    ZeroMemory( &constDesc, sizeof( constDesc ) );
    constDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    constDesc.ByteWidth = sizeof( XMMATRIX );
    constDesc.Usage = D3D11_USAGE_DEFAULT;

    d3dResult = d3dDevice_->CreateBuffer( &constDesc, 0, &mvpCB_ );

    if( FAILED( d3dResult ) )
    {
        return false;
    }


    XMMATRIX view = XMMatrixIdentity( );
    XMMATRIX projection = XMMatrixOrthographicOffCenterLH( 0.0f, 1366.0f, 0.0f, 768.0f, 0.1f, 100.0f );
    vpMatrix_ = XMMatrixMultiply( view, projection );


    D3D11_BLEND_DESC blendDesc;
    ZeroMemory( &blendDesc, sizeof( blendDesc ) );
    blendDesc.RenderTarget[0].BlendEnable = TRUE;
    blendDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
    blendDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
    blendDesc.RenderTarget[0].DestBlend = D3D11_BLEND_ONE;
    blendDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
    blendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ZERO;
    blendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
    blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;


    float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };

    d3dDevice_->CreateBlendState( &blendDesc, &alphaBlendState_ );

    // create the disabled blend state
    blendDesc.RenderTarget[0].BlendEnable = FALSE;
    d3dDevice_->CreateBlendState( &blendDesc, &alphaBlendStateOff );
    d3dContext_->OMSetBlendState( alphaBlendState_, blendFactor, 0xFFFFFFFF );

    // holy shit here we go again
        ID3DBlob* vsBuffer2 = 0;
        compileResult = CompileD3DShader( "TextMap.fx", "VS_Main", "vs_4_0", &vsBuffer2 );

    if( compileResult == false )
    {
        DXTRACE_MSG( "Error compiling the vertex shader!" );
        return false;
    }

    d3dResult = d3dDevice_->CreateVertexShader( vsBuffer2->GetBufferPointer( ),
        vsBuffer2->GetBufferSize( ), 0, &solidColorVS_2 );

        ID3DBlob* psBuffer2 = 0;

    compileResult = CompileD3DShader( "TextureMap.fx", "PS_Main", "ps_4_0", &psBuffer2 );

    if( compileResult == false )
    {
        DXTRACE_MSG( "Error compiling pixel shader!" );
        return false;
    }

    d3dResult = d3dDevice_->CreatePixelShader( psBuffer2->GetBufferPointer( ),
        psBuffer2->GetBufferSize( ), 0, &solidColorPS_2 );

    psBuffer2->Release( );

    return true;
}


void GameSpriteDemo::UnloadContent( )
{
    if( colorMapSampler_ ) colorMapSampler_->Release( );
    if( colorMap_ ) colorMap_->Release( );
    if( solidColorVShaders[0] ) solidColorVShaders[0]->Release( );
    if( solidColorPS_ ) solidColorPS_->Release( );
    if( inputLayout_ ) inputLayout_->Release( );
    if( vertexBuffer_ ) vertexBuffer_->Release( );
    if( mvpCB_ ) mvpCB_->Release( );
    if( alphaBlendState_ ) alphaBlendState_->Release( );
    if( alphaBlendStateOff ) alphaBlendStateOff->Release( );

    colorMapSampler_ = 0;
    colorMap_ = 0;
    solidColorVShaders[0] = 0;
    solidColorPS_ = 0;
    inputLayout_ = 0;
    vertexBuffer_ = 0;
    mvpCB_ = 0;
    alphaBlendState_ = 0;
    alphaBlendStateOff = 0;
}


void GameSpriteDemo::Update( float dt )
{
    // Nothing to update
}

bool GameSpriteDemo::DrawString( char* message, float startX, float startY )
{
    // Size in bytes for a single sprite.
    const int sizeOfSprite = sizeof( VertexPos ) * 6;

    // Demo's dynamic buffer setup for max of 24 letters.
    const int maxLetters = 24;

    int length = strlen( message );

    // Clamp for strings too long.
    if( length > maxLetters )
        length = maxLetters;

    // Char's width on screen.
    float charWidth = 32.0f / (1366.0f*1.0f);

    // Char's height on screen.
    float charHeight = 32.0f / (768.0f*1.0f);

    // Char's texel width.
    float texelWidth = 32.0f / 896.0f;

    // verts per-triangle (3) * total triangles (2) = 6.
    const int verticesPerLetter = 6;

    D3D11_MAPPED_SUBRESOURCE mapResource;
    HRESULT d3dResult = d3dContext_->Map( vertexBuffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapResource );

    if( FAILED( d3dResult ) )
    {
        DXTRACE_MSG( "Failed to map resource!" );
        return false;
    }

    // Point to our vertex buffer's internal data.
    VertexPos *spritePtr = ( VertexPos* )mapResource.pData;

    const int indexA = static_cast<char>( 'A' );
    const int indexZ = static_cast<char>( 'Z' );
    const int index_a = static_cast<char>( 'a' );

    for( int i = 0; i < length; ++i )
    {
        float thisStartX = startX + ( charWidth * static_cast<float>( i ) );
        float thisEndX = thisStartX + charWidth;
        float thisEndY = startY + charHeight;

        spritePtr[0].pos = XMFLOAT3( thisEndX,   thisEndY, 1.0f );
        spritePtr[1].pos = XMFLOAT3( thisEndX,   startY,   1.0f );
        spritePtr[2].pos = XMFLOAT3( thisStartX, startY,   1.0f );
        spritePtr[3].pos = XMFLOAT3( thisStartX, startY,   1.0f );
        spritePtr[4].pos = XMFLOAT3( thisStartX, thisEndY, 1.0f );
        spritePtr[5].pos = XMFLOAT3( thisEndX,   thisEndY, 1.0f );

        int texLookup = 0;
        int letter = static_cast<char>( message[i] );

        if (letter == index_a) {
            texLookup = (indexZ - indexA) + 2;
        }
        else if( letter < indexA || letter > indexZ )
        {
            // Grab one index past Z, which is a blank space in the texture.
            texLookup = ( indexZ - indexA ) + 1;
        }
        else
        {
            // A = 0, B = 1, Z = 25, etc.
            texLookup = ( letter - indexA );
        }

        float tuStart = 0.0f + ( texelWidth * static_cast<float>( texLookup ) );
        float tuEnd = tuStart + texelWidth;

        spritePtr[0].tex0 = XMFLOAT2( tuEnd, 0.0f );
        spritePtr[1].tex0 = XMFLOAT2( tuEnd, 1.0f );
        spritePtr[2].tex0 = XMFLOAT2( tuStart, 1.0f );
        spritePtr[3].tex0 = XMFLOAT2( tuStart, 1.0f );
        spritePtr[4].tex0 = XMFLOAT2( tuStart, 0.0f );
        spritePtr[5].tex0 = XMFLOAT2( tuEnd, 0.0f );

        spritePtr += 6;
    }

    d3dContext_->Unmap( vertexBuffer_, 0 );

   d3dContext_->Draw( 6 * length, 0 );

    return true;
}


void GameSpriteDemo::Render( )
{
    if( d3dContext_ == 0 )
        return;

    float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
    d3dContext_->ClearRenderTargetView( backBufferTarget_, clearColor );

    unsigned int stride = sizeof( VertexPos );
    unsigned int offset = 0;

    d3dContext_->IASetInputLayout( inputLayout_ );
    d3dContext_->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

    d3dContext_->VSSetShader( solidColorVShaders[0], 0, 0 );
    d3dContext_->PSSetShader( solidColorPS_, 0, 0 );

    XMMATRIX world;
    XMMATRIX mvp;
    int index;

    for (int k = 0; k < sprites_.size(); k++) {

    index = sprites_[k].getIndex();
    d3dContext_->IASetVertexBuffers( 0, 1, &vertexBuffers[index], &stride, &offset );
    d3dContext_->PSSetShaderResources( 0, 1, &colorMaps[index] );
    d3dContext_->PSSetSamplers( 0, 1, &colorSamplers[index] );

        world = sprites_[k].GetWorldMatrix();
        mvp = XMMatrixMultiply( world, vpMatrix_ );
        mvp = XMMatrixTranspose( mvp );

        d3dContext_->UpdateSubresource( mvpCB_, 0, 0, &mvp, 0, 0 );
        d3dContext_->VSSetConstantBuffers( 0, 1, &mvpCB_ );

        d3dContext_->Draw( 6, 0 );
    }



    // render text



        DisableBlending();

    d3dContext_->IASetVertexBuffers( 0, 1, &vertexBuffer_, &stride, &offset );
    d3dContext_->PSSetShaderResources( 0, 1, &colorMap_ );
    d3dContext_->PSSetSamplers( 0, 1, &colorMapSampler_ );
    d3dContext_->VSSetShader( solidColorVS_2, 0, 0 );
    d3dContext_->PSSetShader( solidColorPS_2, 0, 0 );


    DrawString( "PROTOTYPE TEXT", -0.2f, 0.0f );

    swapChain_->Present( 0, 0 );
}

ID3D11ShaderResourceView* GameSpriteDemo::getColorMap(int index) {
    return colorMaps[index];
}

// this functions disables the alpha blending
void GameSpriteDemo::DisableBlending() {
        float blendFactor[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
        d3dContext_->OMSetBlendState( alphaBlendStateOff, blendFactor, 0xFFFFFFFF );
}

启用混合绘制时的结果屏幕 http://i49.tinypic.com/33kao9v.jpg

这里是我正在使用的两个FX文件的HLSL代码(第一个是sprite,第二个是文本)

TextureMap.fx

cbuffer cbChangesPerFrame : register( b0 )
{
    matrix mvp_;
};


Texture2D colorMap_ : register( t0 );
SamplerState colorSampler_ : register( s0 );

struct VS_Input
{
    float4 pos  : POSITION;
    float2 tex0 : TEXCOORD0;
};

struct PS_Input
{
    float4 pos  : SV_POSITION;
    float2 tex0 : TEXCOORD0;
};


PS_Input VS_Main( VS_Input vertex )
{
    PS_Input vsOut = ( PS_Input )0;
    vsOut.pos = mul( vertex.pos, mvp_ );
    vsOut.tex0 = vertex.tex0;

    return vsOut;
}


float4 PS_Main( PS_Input frag ) : SV_TARGET
{
    return colorMap_.Sample( colorSampler_, frag.tex0 );
}

TextMap.fx

Texture2D colorMap_ : register( t0 );
SamplerState colorSampler_ : register( s0 );


struct VS_Input

    {
        float4 pos  : POSITION;
        float2 tex0 : TEXCOORD0;
    };

    struct PS_Input
    {
        float4 pos  : SV_POSITION;
        float2 tex0 : TEXCOORD0;
    };


    PS_Input VS_Main( VS_Input vertex )
    {
        PS_Input vsOut = ( PS_Input )0;
        vsOut.pos = vertex.pos;
        vsOut.tex0 = vertex.tex0;

        return vsOut;
    }


    float4 PS_Main( PS_Input frag ) : SV_TARGET
    {
        return colorMap_.Sample( colorSampler_, frag.tex0 );
    }

我想知道可能会使用像素着色器为特定的2D图像执行alpha混合,但我的第一次尝试根本没用。

希望有人能以某种方式找到解决方案:)

再次感谢您的帮助。

0 个答案:

没有答案