Æ÷½ºÆ®ÀÌÆåÆ® ÇÁ·¹ÀÓ

±×¸²ÀÚ¸ÅÇÎÀ» ¶° ¿Ã¸®¸é¼­ Æ÷½ºÆ®ÀÌÆåÆ®¸¦ ÀÛ¼ºÇØ º¸ÀÚ.

ÀÌÀüÀåÀÇ tutorial10ÀåÀÇ ColorConversion3.rfx ÆÄÀÏÀ» NoEffect.rfx, Grayscale.rfx, Sepia.rfx ÆÄÀÏ·Î ÀúÀåÇÑ´Ù.

NoEffect.rfx, Grayscale.rfx, Sepia.rfx´Â µ¿ÀÏÇÑ À̸§ÀÇ Æнº¸¸ ³²±â°í ³ª¸ÓÁö Æнº´Â »èÁ¦ÇÑ´Ù.

±×¸²ÀÚ¸ÅÇο¡¼­´Â »ç°¢Çü ¸Þ½¬¸¦ »ç¿ëÇߴµ¥, ¿©±â¼­´Â C++ Äڵ忡¼­ Á÷Á¢ ¸¸µé°Ú´Ù.

»ç°¢Çü ¸Þ½¬ ¸¸µé±â

Á¤Á¡ À§Ä¡¿Í UV ÁÂÇ¥ ¸¸À¸·Î »ç°¢Çü ¸Þ½¬¸¦ ¸¸µç´Ù.

Á¤Á¡¼±¾ð, Á¤Á¡¹öÆÛ, »öÀιöÆÛ¸¦ ¼±¾ðÇÑ ±¸Á¶Ã¼¸¦ ¸¸µç´Ù.
Àü¿ªº¯¼ö gScreenQuadMesh¸¦ ¼±¾ðÇÑ´Ù.

//½ºÅ©¸° Äõµå ¸Þ½¬
struct ScreenQuadMesh
{
    int size;
    LPDIRECT3DVERTEXDECLARATION9    decl;
    LPDIRECT3DVERTEXBUFFER9            vb;
    LPDIRECT3DINDEXBUFFER9            ib;
};
ScreenQuadMesh gScreenQuadMesh = {0, NULL, NULL, NULL};

½ºÅ©¸° Äõµå ¸Þ½¬¸¦ ÇØÁ¦ÇÑ´Ù.

void ReleaseScreenMesh()
{
    _RELEASE_(gScreenQuadMesh.decl);
    _RELEASE_(gScreenQuadMesh.vb);
    _RELEASE_(gScreenQuadMesh.ib);
}

½ºÅ©¸° Äõµå ¸Þ½¬¸¦ »ý¼ºÇÑ´Ù.

void InitScreenMesh()
{
    ScreenQuadMesh_CreateVertexDeclaration( gScreenQuadMesh);
    ScreenQuadMesh_CreateVertexBuffer( gScreenQuadMesh);
    ScreenQuadMesh_CreateIndexBuffer( gScreenQuadMesh);
}

¸Þ¸ð¸® ±¸Á¶¸¦ ´ÙÀÌ·ºÆ® X µð¹ÙÀ̽º¿¡ ¾Ë·ÁÁÖ±â À§ÇØ Á¤Á¡ ¼±¾ðÀ» »ý¼ºÇÑ´Ù.

HRESULT ScreenQuadMesh_CreateVertexDeclaration( ScreenQuadMesh& quadMesh)
{
    // Á¤Á¡ ¼±¾ðÀ» ¸¸µç´Ù
    D3DVERTEXELEMENT9 vtxDesc[3];
    int offset = 0;
    int i = 0;

    // À§Ä¡
    vtxDesc[i].Stream = 0;
    vtxDesc[i].Offset = offset;
    vtxDesc[i].Type = D3DDECLTYPE_FLOAT3;
    vtxDesc[i].Method = D3DDECLMETHOD_DEFAULT;
    vtxDesc[i].Usage = D3DDECLUSAGE_POSITION;
    vtxDesc[i].UsageIndex = 0;

    offset += sizeof(float)* 3;
    ++i;

    // UVÁÂÇ¥ 0
    vtxDesc[i].Stream = 0;
    vtxDesc[i].Offset = offset;
    vtxDesc[i].Type = D3DDECLTYPE_FLOAT2;
    vtxDesc[i].Method = D3DDECLMETHOD_DEFAULT;
    vtxDesc[i].Usage = D3DDECLUSAGE_TEXCOORD;
    vtxDesc[i].UsageIndex = 0;

    offset += sizeof(float)* 2;
    ++i;

    // Á¤Á¡Æ÷¸ËÀÇ ³¡ÀÓÀ» Ç¥Çö (D3DDECL_END())
    vtxDesc[i].Stream = 0xFF;
    vtxDesc[i].Offset = 0;
    vtxDesc[i].Type = D3DDECLTYPE_UNUSED;
    vtxDesc[i].Method = 0;
    vtxDesc[i].Usage = 0;
    vtxDesc[i].UsageIndex = 0;

    quadMesh.size = 0;
    return gD3DDevice->CreateVertexDeclaration(vtxDesc, &quadMesh.decl);    
}

 

    vtxDesc[i].Stream = 0;
    vtxDesc[i].Offset = offset;
    vtxDesc[i].Type = D3DDECLTYPE_FLOAT3;
    vtxDesc[i].Method = D3DDECLMETHOD_DEFAULT;
    vtxDesc[i].Usage = D3DDECLUSAGE_POSITION;
    vtxDesc[i].UsageIndex = 0;

Stream : ½ºÆ®¸² À妽º
Offset : Á¤Á¡ Á¤º¸°¡ ½ÃÀÛÇÏ´Â À§Ä¡
type : µ¥ÀÌÅÍ Çü
Method : D3DDECLMETHOD_DEFAULT µðÆúÆ® ¼³Á¤
Usage : ÀÌ ¿ä¼ÒÀÇ »ç¿ë¿ëµµ
UsageIndex : TEXCOORDÀÇ À妽º·Î, ÅؽºÃĸ¦ »ç¿ëÇÏÁö ¾ÊÀ¸¹Ç·Î 0ÀÌ´Ù.

¼ÎÀÌ´õ ÀÚ¿ø ó¸®

Æ÷½ºÆ®ÇÁ·Î¼¼½Ì¿¡ »ç¿ëÇÒ ¼ÎÀÌ´õ ¸®¼Ò½º¸¦ ¸¸µç´Ù.

struct ScreenEffect
{
    LPD3DXEFFECT noEffect;
    LPD3DXEFFECT grayScale;
    LPD3DXEFFECT sepia;
};
ScreenEffect gScreenEffect = { NULL, NULL, NULL};

½ºÅ©¸°¿ë ·»´õŸ°Ù º¯¼ö ¼±¾ð

//½ºÅ©¸° ·»´õŸ°Ù
LPDIRECT3DTEXTURE9 gScreenRenderTarget = NULL;

¸®¼Ò½ºµéÀ» ÇØÁ¦ÇÑ´Ù.

void ReleaseScreenEffect()
{
    _RELEASE_(gScreenEffect.noEffect);
    _RELEASE_(gScreenEffect.grayScale);
    _RELEASE_(gScreenEffect.sepia);    

    _RELEASE_(gScreenRenderTarget);
}

·»´õŸ°ÙÀ» âÀÇ Æø°ú ³ôÀÌ·Î »ý¼ºÇÑ´Ù.
ÅؽºÃ³ Æ÷¸ËÀº Çϵå¿þ¾î ¹é¹öÆÛ Æ÷¸Ë°ú ¸¶Âù°¡Áö·Î 8ºñÆ® RGB ä³Î D3DFMT_X8R8G8B8·Î ÇÑ´Ù.
gRenderScrWidth, gRenderScrHeight´Â ¹é¹öÆÛÀÇ Æø°ú ³ôÀÌ´Ù.
´Ù¸¥ ¼öÄ¡¸¦ ³Ö°Ô µÇ¸é È­¸éÀÌ Á¤»óÀûÀ¸·Î º¸ÀÌÁö ¾ÊÀ»°ÍÀÌ´Ù.

bool InitScreenRenderTarget()
{
    //·»´õŸ°Ù »ý¼º
    if( FAILED(gD3DDevice->CreateTexture(
            gRenderScrWidth, gRenderScrHeight,
            1,
            D3DUSAGE_RENDERTARGET,
            D3DFMT_X8R8G8B8,D3DPOOL_DEFAULT,
            &gScreenRenderTarget, NULL)))
    {
        return false;
    }

    return true;
}

LoadAsset( )¿¡¼­ ¼ÎÀÌ´õ¸¦ ·ÎµùÇÑ´Ù.

// ¼ÎÀÌ´õ ·Îµù
gScreenEffect.noEffect = LoadShader("NoEffect.fx");
if(gScreenEffect.noEffect == NULL)
    return false;

gScreenEffect.grayScale = LoadShader("GrayScale.fx");
if(gScreenEffect.grayScale == NULL)
    return false;

gScreenEffect.sepia = LoadShader("Sepia.fx");
if(gScreenEffect.sepia == NULL)
    return false;

·»´õ¸µ - RenderScene( ) - ¸Þ½Ã ±×¸®±â

Çϵå¿þ¾î ¹é ¹öÆÛ¸¦ ÀúÀå ÈÄ, ·»´õ·¯ÅؽºÃĸ¦ ·»´õŸ°ÙÀ¸·Î ÁöÁ¤ÇÑ´Ù.
Çϵå¿þ¾î ±íÀ̹öÆÛ¸¦ »ç¿ëÇÏÁö ¾Ê´Â ÀÌÀ¯´Â ·»´õŸ°ÙÀÇ Å©±â°¡ Çϵå¿þ¾î ±íÀÌ ¹öÆÛÀÇ Å©±â¿Í µ¿ÀÏÇϱ⠶§¹®ÀÌ´Ù.

//1. Àå¸éÀ» ±×¸°´Ù

//¹é¹öÆÛ ÀúÀå
LPDIRECT3DSURFACE9 pHWBackBuffer = NULL;
gD3DDevice->GetRenderTarget(0, &pHWBackBuffer);

//·»´õ·¯ÅؽºÃĸ¦ ·»´õŸ°ÙÀ¸·Î ¼³Á¤
LPDIRECT3DSURFACE9 pSceneSurface = NULL;
if (SUCCEEDED(gScreenRenderTarget->GetSurfaceLevel(0, &pSceneSurface)))
{
    gD3DDevice->SetRenderTarget(0, pSceneSurface);
    pSceneSurface->Release();
    pSceneSurface = NULL;
}

·»´õŸ°ÙÀ» »õ·Ó°Ô ¼³Á¤Ç߱⠶§¹®¿¡ Àå¸éÀ» Áö¿î´Ù.

gD3DDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 1.0f, 0);

Çà·Ä¸¦ ¼³Á¤ ÈÄ Àü¿ªº¯¼ö¸¦ ¼³Á¤ÇÑ´Ù.

// ½¦ÀÌ´õ Àü¿ªº¯¼öµéÀ» ¼³Á¤
gShader->SetMatrix("gWorldMat", &matWorld);
gShader->SetMatrix("gWorldViewProjMat", &matWorldViewProjection);

gShader->SetVector("gLightPos", &gWorldLightPos);
gShader->SetVector("gViewPos", &gWorldCameraPos);

gShader->SetVector("gLightColor", &gLightColor);
gShader->SetTexture("DiffuseMap_Tex", gStoneDM);
gShader->SetTexture("SpecularMap_Tex", gStoneSM);
gShader->SetTexture("NormalMap_Tex", gStoneNM);
gShader->SetTexture("EnvironmentMap_Tex", gSnowENV);

·»´õ·¯ ÅؽºÃÄ¿¡ ±×¸°´Ù.

// ½¦ÀÌ´õ¸¦ ½ÃÀÛÇÑ´Ù.
UINT numPasses = 0;
gShader->Begin(&numPasses, NULL);
{
    for (UINT i = 0; i < numPasses; ++i)
    {
        gShader->BeginPass(i);
        {
            gMesh->DrawSubset(0);
        }
        gShader->EndPass();
    }
}
gShader->End();

·»´õ¸µ - RenderScene( ) - Æ÷½ºÆ® ÇÁ·Î¼¼½Ì

·»´õ·¯ ÅؽºÃÄ¿¡ ±×¸° À̹ÌÁö¸¦ Æ÷½ºÆ® ÇÁ·Î¼¼½Ì 󸮸¦ ÇÏ¿© ½ºÅ©¸° Æò¸é¿¡ ±×·Áº¸ÀÚ.

ÀúÀåÇØ µÎ¾ú´ø Çϵå¿þ¾î ¹é ¹öÆÛ¸¦ ·»´õŸ°ÙÀ¸·Î ¼³Á¤ÇÑ´Ù.

//2. Æ÷½ºÆ®ÇÁ·Î¼¼½ÌÀ» Àû¿ëÇÑ´Ù.

// Çϵå¿þ¾î ¹é¹öÆÛ¸¦ »ç¿ëÇÑ´Ù.
gD3DDevice->SetRenderTarget(0, pHWBackBuffer);
pHWBackBuffer->Release();
pHWBackBuffer = NULL;

·»´õ·¯ ÅؽºÃĸ¦ ·»´õŸ°ÙÀ¸·Î ¼³Á¤ÇÑ µÚ Æнº¸¦ ½ÃÀÛÇÑ´Ù.

useShader->SetTexture("SceneTexture_Tex", gScreenRenderTarget);
useShader->Begin(&numPasses, NULL);
{
    for (UINT i = 0; i < numPasses; ++i)
    {
        useShader->BeginPass(i);
        {

È­¸é¿¡ ½ºÅ©¸° Æò¸é¿¡ ·»´õ·¯ÅؽºÃĸ¦ ±×¸®°í Æнº¸¦ ³¡³½´Ù

            // È­¸é°¡µæ »ç°¢ÇüÀ» ±×¸°´Ù.
            gD3DDevice->SetStreamSource(0, gScreenQuadMesh.vb, 0, sizeof(float)* 5);
            gD3DDevice->SetIndices(gScreenQuadMesh.ib);
            gD3DDevice->SetVertexDeclaration(gScreenQuadMesh.decl);
            gD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 6, 0, 2);
        }
        useShader->EndPass();
    }
}
useShader->End();

Key 1, 2, 3¿¡ µû¶ó NoEffect, Grayscale, Sepia ¼ÎÀÌ´õ¸¦ ½ÇÇàÇÑ´Ù.

void main_OnKeydown(HWND hwnd, UINT vk, BOOL fDown, int cRepeat, UINT flags)
{
    switch (vk)
    {
    case '1':
    case '2':
    case '3':
        gPostProcessIndex = vk - '0' - 1;
        break;
    }
}

´Ù¿î·Îµå : PostProcssingShader.zip       DxDemo_PostProcessing.zip