⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filterblit.cpp

📁 游戏编程精华02-含有几十个游戏编程例子
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	D3DXMATRIX matProj;
	D3DXMATRIX matViewProj;
	D3DXMATRIX matWorldViewProj;

    // write to constant memory which uv-offsets to use
    D3DXVECTOR4     offset(0.0f, 0.0f, 0.0f, 0.0f);

	switch (meDisplayOption)
    {
        case BOX9_FILTER:
            offset.x = 4.0f;
            break;
        case SHARPEN_FILTER:
            offset.x = 3.0f;
            break;
        case BOX16_FILTER:
            offset.x = 2.0f;
            break;
        default:
            offset.x = 1.0f;
            break;
    }
    m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);

	// Disable culling
	m_pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);

    // set render state 
	m_pD3DDev->SetVertexShader(m_dwVertexShader);
	m_pD3DDev->SetStreamSource(0, m_pVertexBuffer, sizeof(QuadVertex));


	D3DXVECTOR3 const vEyePt    = D3DXVECTOR3( 0.0f, 0.0f, -5.0f );
	D3DXVECTOR3 const vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
	D3DXVECTOR3 const vUp       = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );

	// Set World, View, Projection, and combination matrices.
	D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUp);
	D3DXMatrixOrthoLH(&matProj, 4.0f, 4.0f, 0.2f, 20.0f);

    D3DXMatrixMultiply(&matViewProj, &matView, &matProj);

    // draw a single quad to texture:
    // the quad covers the whole "screen" exactly
	D3DXMatrixScaling(&matWorld, 2.0f, 2.0f, 1.0f);
	D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
    D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
	m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);

    // turn on our special filtering pixel shader
    if (meDisplayOption != LUMINANCE_EDGE)
        m_pD3DDev->SetPixelShader( (meDisplayOption == SHARPEN_FILTER) ? 
                                      m_dwSharpenPixelShader
                                    : m_dwBlurPixelShader);	
    
    // draw multiple passes        
    for (int i = 0; i < kMaxNumPasses; ++i)
    {
        hr = m_pD3DDev->SetRenderTarget(mpFilterTarget[i], NULL);
	    hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB( 0xFF, 0x0, 0x0 ), 1.0, 0);

        if (meDisplayOption == LUMINANCE_EDGE)
        {
            switch (i)
            {
                case 0:
                    m_pD3DDev->SetPixelShader(m_dwLuminancePixelShader);	
                    m_pD3DDev->SetTexture(0, mpTextureToFilter->GetTexture());
                    m_pD3DDev->SetTexture(1, mpTextureToFilter->GetTexture());
                    m_pD3DDev->SetTexture(2, mpTextureToFilter->GetTexture());
                    m_pD3DDev->SetTexture(3, mpTextureToFilter->GetTexture());
                    break;
                case 1:
                    m_pD3DDev->SetPixelShader(m_dwLuminanceSensitiveDiagEdgePixelShader);	
                    break;
                case 2:
                    m_pD3DDev->SetPixelShader(m_dwLuminanceDiagEdgePixelShader);	
                    break;
                default:
                    break;
            }
        }
        else
        {
            switch (i)
            {
                case 0:
                    m_pD3DDev->SetTexture(0, mpTextureToFilter->GetTexture());
                    m_pD3DDev->SetTexture(1, mpTextureToFilter->GetTexture());
                    m_pD3DDev->SetTexture(2, mpTextureToFilter->GetTexture());
                    m_pD3DDev->SetTexture(3, mpTextureToFilter->GetTexture());
                    break;
                default:
                    m_pD3DDev->SetTexture(0, mpTextureFiltered[i-1]);
                    m_pD3DDev->SetTexture(1, mpTextureFiltered[i-1]);
                    m_pD3DDev->SetTexture(2, mpTextureFiltered[i-1]);
                    m_pD3DDev->SetTexture(3, mpTextureFiltered[i-1]);
                    break;
            }
        }
        
        // draw the fan with displaced texture coordinates
        hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
    }

    // then switch back to normal rendering 
    hr = m_pD3DDev->SetRenderTarget(mpBackbufferColor, mpBackbufferDepth);
	hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0xAA, 0xAA, 0xAA ), 1.0, 0);

    // turn off pixel shading
    m_pD3DDev->SetPixelShader(0);	

    // draw quad in upper left corner: original texture
	D3DXMatrixTranslation(&matWorld, -1.0f, 1.0f, 0.0f);
	D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
    D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
	m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);

    // reset offsets to 0 (ie no offsets)
    offset.x = 0.0f;
    m_pD3DDev->SetVertexShaderConstant(CV_UV_OFFSET_TO_USE, &offset, 1);

    m_pD3DDev->SetTexture(0, mpTextureToFilter->GetTexture());
	hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);

    // draw quads in the other corners, use generated textures
    for (int j = 0; j < 3; ++j)
    {
        D3DXMatrixTranslation(&matWorld, (j == 2) ? -1.0f :  1.0f, 
                                         (j == 0) ?  1.0f : -1.0,
                                         0.0f);
	    D3DXMatrixMultiply(&matWorldViewProj, &matWorld, &matViewProj);
        D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
	    m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);

        m_pD3DDev->SetTexture(0, mpTextureFiltered[j]);
	    hr = m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
    }
	return hr;
}

HRESULT CFilterBlit::CreateTextureRenderTarget()
{
    HRESULT         hr;

    // get a pointer to the current back-buffer (so we can restore it later)
	m_pD3DDev->GetRenderTarget(        &mpBackbufferColor );
	m_pD3DDev->GetDepthStencilSurface( &mpBackbufferDepth );
	_ASSERT( mpBackbufferColor != NULL );
	_ASSERT( mpBackbufferDepth != NULL );

    // get the description for the texture we want to filter
	D3DSURFACE_DESC ddsd;
    mpTextureToFilter->GetTexture()->GetLevelDesc(0, &ddsd);

    // create new textures just like the current texture
    for (int i = 0; i < kMaxNumPasses; ++i)
    {
        hr = m_pD3DDev->CreateTexture(ddsd.Width, ddsd.Height, 1, 
                                      D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, 
                                      D3DPOOL_DEFAULT, &mpTextureFiltered[i]);
        if (FAILED(hr))
        {
		    m_strLastError = "Can't CreateTexture!\n";
            _ASSERT(false);
            return E_FAIL;
        }

        hr = mpTextureFiltered[i]->GetSurfaceLevel(0, &mpFilterTarget[i]);
        if (FAILED(hr))
        {
		    m_strLastError = "Can't Get to top-level texture!\n";
            _ASSERT(false);
            return E_FAIL;
        }

        // set our render target to the new and shiny textures without depth
        hr = m_pD3DDev->SetRenderTarget(mpFilterTarget[i], NULL);
        if (FAILED(hr))
        {
		    m_strLastError = "Can't SetRenderTarget to new surface!\n";
            _ASSERT(false);
            return E_FAIL;
        }
    }

    // switch back to conventional back-buffer
    hr = m_pD3DDev->SetRenderTarget(mpBackbufferColor, mpBackbufferDepth);
    if (FAILED(hr))
    {
		m_strLastError = "Can't SetRenderTarget to original back-buffer surfaces!\n";
        _ASSERT(false);
        return E_FAIL;
    }

    return S_OK;
}

void CFilterBlit::CreateAndWriteUVOffsets(int width, int height)
{
	// displace texture-uvs so that the sample points on the 
    // texture describe 
    // i)   a square around the texel to sample.
    //      the edges of the square are distance s from the center texel.
    //      Due to bilinear filtering and application of equal weights (1/4) 
    //      in the pixel shader, the following filter is implemented for the 9 samples
    //          abc
    //          def
    //          ghi:
    //      filtered pixel = (s*s)/4 (a+c+g+i) + (s-s*s)/2 (b+d+f+h) + (1-s)^2 e
    //         Thus, choosing s = 0 means no filtering (also no offsets)
    //      s = 2/3 results in an equally weighted, 9-sample box-filter (and is called
    //      type4) and s = 1/2 results in a circular cone-filter (and is called type1).
    // ii) a square around the texel to sample, so as to include sixteen texels:
    //          abcd
    //          efgh
    //          ijkl
    //          mnop
    //      Center texel is assumed to be "j", and offsets are made so that the texels
    //      are the combinations of (a, b, e, f), (c, d, g, h), (i, j, m, n), and 
    //      (k, l, o, p)
    // iii) A quad-sample filter:
    //         a
    //         b
    //        cde
    //      Center texel is "b" and sampled dead center.  The second sample is 
    //      dead-center "a", and the last two samples are interpolations between
    //      (c,d) and (d,e).  Connecting the samples with the center pixel should 
    //      produce three lines that measure the same angle (120 deg) between them.
    //      This sampling pattern may be rotated around "b".

    // first the easy one: no offsets
    float const     noOffsetX[4] = { 0.0f, 0.0f, 0.0f, 0.0f}; 
    float const     noOffsetY[4] = { 0.0f, 0.0f, 0.0f, 0.0f};

    float const     kPerTexelWidth  = 1.0f/static_cast<float>(width);
    float const     kPerTexelHeight = 1.0f/static_cast<float>(height);
    float           s               = 0.5f;
    float const     eps             = 10.0e-4f;
    float const     rotAngle1       = D3DXToRadian( 0.0f );
    float const     rotAngle2       = rotAngle1 + D3DXToRadian(120.0f); 
    float const     rotAngle3       = rotAngle1 + D3DXToRadian(240.0f); 

    // Change filter kernel for 9-sample box filtering, but for edge-detection we are 
    // going to use interpolated texels.  Why?  Because we detect diagonal edges only
    // and the vertical and horizontal filtering seems to help.
        
    float const type1OffsetX[4] = { -s * kPerTexelWidth, 
                                    -s * kPerTexelWidth,  
                                     s * kPerTexelWidth,   
                                     s * kPerTexelWidth  };
    float const type1OffsetY[4] = { -s * kPerTexelHeight, 
                                     s * kPerTexelHeight, 
                                     s * kPerTexelHeight, 
                                    -s * kPerTexelHeight };

    // we have to bring the 16 texel-sample-filter a bit closer to the center to avoid 
    // separation due to floating point inaccuracies.
    float const type2OffsetX[4] = { -.5f * kPerTexelWidth + eps,  
                                    -.5f * kPerTexelWidth + eps, 
                                    1.5f * kPerTexelWidth - eps, 
                                    1.5f * kPerTexelWidth - eps };
    float const type2OffsetY[4] = { -.5f * kPerTexelHeight+ eps, 
                                    1.5f * kPerTexelHeight- eps, 
                                    1.5f * kPerTexelHeight- eps, 
                                    -.5f * kPerTexelHeight+ eps };

    float const type3OffsetX[4] = {0.0f,  sinf(rotAngle1)*kPerTexelWidth,  
                                          sinf(rotAngle2)*kPerTexelWidth,  
                                          sinf(rotAngle3)*kPerTexelWidth  };
    float const type3OffsetY[4] = {0.0f, -cosf(rotAngle1)*kPerTexelHeight, 
                                         -cosf(rotAngle2)*kPerTexelHeight, 
                                         -cosf(rotAngle3)*kPerTexelHeight };

    s = 2.0f/3.0f;      // same as type 1, except s is different
    float const type4OffsetX[4] = { -s * kPerTexelWidth, 
                                    -s * kPerTexelWidth,  
                                     s * kPerTexelWidth,   
                                     s * kPerTexelWidth  };
    float const type4OffsetY[4] = { -s * kPerTexelHeight, 
                                     s * kPerTexelHeight, 
                                     s * kPerTexelHeight, 
                                    -s * kPerTexelHeight };

    // write all these offsets to constant memory
    for (int i = 0; i < 4; ++i)
    {
        D3DXVECTOR4  noOffset(      noOffsetX[i],    noOffsetY[i], 0.0f, 0.0f);
        D3DXVECTOR4  type1Offset(type1OffsetX[i], type1OffsetY[i], 0.0f, 0.0f);
        D3DXVECTOR4  type2Offset(type2OffsetX[i], type2OffsetY[i], 0.0f, 0.0f);
        D3DXVECTOR4  type3Offset(type3OffsetX[i], type3OffsetY[i], 0.0f, 0.0f);
        D3DXVECTOR4  type4Offset(type4OffsetX[i], type4OffsetY[i], 0.0f, 0.0f);

    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_NO_OFFSET + 5*i, &noOffset,    1);
    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_TYPE1     + 5*i, &type1Offset, 1);
    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_TYPE2     + 5*i, &type2Offset, 1);
    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_TYPE3     + 5*i, &type3Offset, 1);
    	m_pD3DDev->SetVertexShaderConstant(CV_UV_T0_TYPE4     + 5*i, &type4Offset, 1);
    }
}

void CFilterBlit::Keyboard(DWORD dwKey, UINT nFlags, bool bDown)
{
    unsigned int option = static_cast<unsigned int>(meDisplayOption); 
	eEBKeyAction Action = TranslateEffectKey(dwKey, nFlags, bDown);
	
    switch ( Action )
    {
		case EB_HELP:
		{
			::MessageBoxEx( NULL, " Help : F1 - Help \n\n Home - Reset To Defaults \n\n W - Wireframe Toggle \n\n +/- - Change Filter Mode",
				   "Help", MB_ICONINFORMATION | MB_TASKMODAL, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) );
		}
		break;

		case EB_WIREFRAME:
        {
            mbWireFrame = !mbWireFrame;
            m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
        }
		break;

		case EB_RESET:
        {
	        meDisplayOption = meInitDisplayOption;
            mbWireFrame = false;
            m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
        }
		break;

        case EB_ADD:
            if (++option >= NUM_FILTER_OPTIONS)
                option = FIRST_FILTER_OPTION;
            meDisplayOption = static_cast<eFilterOptions>(option);
            break;

        case EB_SUBTRACT:
            if (option == FIRST_FILTER_OPTION)
                option = NUM_FILTER_OPTIONS-1;
            else
                --option;
            meDisplayOption = static_cast<eFilterOptions>(option);
            break;

        default:
            break;
    }
    
    switch (meDisplayOption)
	{
		case CONE_FILTER:
		case BOX9_FILTER:
		case BOX16_FILTER:
			m_strEffectPixelShader = GetFilePath("BlurBlit.nvp");
			break;
		case SHARPEN_FILTER:
			m_strEffectPixelShader = GetFilePath("SharpenBlit.nvp");
				break;
		case LUMINANCE_EDGE:
			m_strEffectPixelShader = GetFilePath("LuminanceDiagEdgeBlit.nvp");
			break;
		default:
		;
	}
	m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PIXELSHADERS;

}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -