2014-11-25 150 views
0

我創建了一個簡單的着色器效果,它必須繪製左半部分是藍色,右半部分是紅色。但是這種轉變不是豔麗的色彩,並帶有漸變發見圖片:enter image description hereDirectX 9 +着色器效果:禁用顏色的平滑過渡

我需要關閉的色彩平滑過渡喜歡這裏: enter image description here

着色效果代碼

struct VSInputTxVc 
{ 
    float4 Position : POSITION; 
    float2 TexCoord : TEXCOORD0; 
    float4 Color  : COLOR; 
}; 

struct VS_OUTPUT 
{ 
    float4 Position : POSITION; 
    float4 Color : COLOR; 
}; 

//Vertex Shader 
VS_OUTPUT RenderSceneVS(VSInputTxVc VertexIn) 
{ 
    VS_OUTPUT VertexOut; 
    VertexOut.Position = VertexIn.Position; 

    if(VertexOut.Position.x > 0) 
    { 
     VertexOut.Color = float4(1,0,0,1); // Right half-part must have red color 
    } 
    else 
    { 
     VertexOut.Color = float4(0,0,1,1); // Left half-part must have blue color 
    } 

    return VertexOut; 
} 

//Pixel Shader 
float4 RenderScenePS(float4 Color : COLOR) : COLOR 
{ 
    return Color; 
} 

technique RenderScene 
{ 
    pass P0 
    { 
     VertexShader = (compile vs_1_1 RenderSceneVS()); 
     PixelShader = (compile ps_2_0 RenderScenePS()); 
    } 
} 

我繪製了全屏原始{-1,-1:-1,1:1,-1:1,1},並且我使用了不同的混合模式,但沒有幫助。

C++代碼:

//Create the Direct3D Object 
    LPDIRECT3D9 pD3D = NULL; 
    if(NULL == (pD3D = Direct3DCreate9(D3D_SDK_VERSION))) 
     return E_FAIL; 

    //Setup the device presentation parameters 
    D3DPRESENT_PARAMETERS d3dpp; 
    ZeroMemory(&d3dpp, sizeof(d3dpp)); 
    d3dpp.Windowed = TRUE; 
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 
    d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; 

    //The final step is to use the IDirect3D9::CreateDevice method to create the Direct3D device, as illustrated in the 
    //following code example. 
    LPDIRECT3DDEVICE9 pd3dDevice = NULL; 
    if(FAILED(pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 
            D3DCREATE_HARDWARE_VERTEXPROCESSING, 
            &d3dpp, &pd3dDevice))) 
    { 
     MessageBox(hWnd, L"No HAL HARDWARE_VERTEXPROCESSING! Sample will exit!", NULL, 0); 
     pD3D->Release(); 
     pD3D = NULL; 
     return E_FAIL; 
    } 

    //set the vertex buffer size 4 vertices * vertex structure size 
    UINT uiBufferSize = 4*sizeof(COLORED_VERTEX); 

    //create the buffer 
    if(FAILED(pd3dDevice->CreateVertexBuffer(uiBufferSize, 
      D3DUSAGE_WRITEONLY, D3DFVF_COLOREDVERTEX, D3DPOOL_DEFAULT, &g_lpVertexBuffer, NULL))) 
     return E_FAIL; 

    COLORED_VERTEX* pVertices; 
    //lock the buffer for writing 
    if(FAILED(g_lpVertexBuffer->Lock(0, uiBufferSize, (void**)&pVertices, 0))) 
     return E_FAIL; 

    //write the vertices. Here a simple rectangle 
    pVertices[0].x = -1.0f; //left 
    pVertices[0].y = -1.0f; //bottom 
    pVertices[0].z = 0.0f; 
    pVertices[0].color = 0xffff0000; //red 

    pVertices[1].x = -1.0f; //left 
    pVertices[1].y = 1.0f; //top 
    pVertices[1].z = 0.0f; 
    pVertices[1].color = 0xff0000ff; //blue 

    pVertices[2].x = 1.0f; //right 
    pVertices[2].y = -1.0f; //bottom 
    pVertices[2].z = 0.0f; 
    pVertices[2].color = 0xff00ff00; //green 

    pVertices[3].x = 1.0f; //right 
    pVertices[3].y = 1.0f; //top 
    pVertices[3].z = 0.0f; 
    pVertices[3].color = 0xffffffff; //white 

    //unlock the buffer 
    g_lpVertexBuffer->Unlock(); 

    //set the Vertex Format 
    pd3dDevice->SetFVF(D3DFVF_COLOREDVERTEX); 

    //transfer the buffer to the gpu 
    pd3dDevice->SetStreamSource(0, g_lpVertexBuffer, 0, sizeof(COLORED_VERTEX)); 

    //create an effect 
    ID3DXBuffer* errorBuffer = 0; 
    wchar_t EffectFileName[] = L"MinimalEffect.fx"; 
    if(FAILED(D3DXCreateEffectFromFile(pd3dDevice, EffectFileName, NULL, 
     NULL, D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY, NULL, &g_lpEffect, &errorBuffer))) 
    { 
     wchar_t buf[2048]; 
     wchar_t tmp[2048]; 
     swprintf_s(buf, L"D3DXCreateEffectFromFile() Error create of effect \"%s\" \n\n", EffectFileName); 
     if(errorBuffer) 
     { 
      lstrcatW(buf, charToWchar_t((char*)errorBuffer->GetBufferPointer(), tmp)); 
      errorBuffer->Release(); 
     } 
     MessageBox(hWnd, buf, NULL, 0); 
     pD3D->Release(); 
     pD3D = NULL; 
     return E_FAIL; 
    } 

    // Choice the tehnique of shader 
    D3DXHANDLE hTechnick; 
    if(D3D_OK != g_lpEffect->FindNextValidTechnique(NULL, &hTechnick)) 
    { 
     wchar_t buf[1024]; 
     swprintf_s(buf, L"[FindNextValidTechnique] No finded any valid tehnique in shader effect. \n\n File: \"%s\"", 
     EffectFileName); 
     MessageBoxW(hWnd, buf, L"Error", MB_OKCANCEL|MB_SETFOREGROUND|MB_TOPMOST); 
     return false; 
    } 
    g_lpEffect->SetTechnique(hTechnick); 

    //D3DXMatrixIdentity(&g_ShaderMatrix); 
    //g_lpEffect->SetMatrix("ShaderMatrix", &g_ShaderMatrix); 

    //pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 
    //pd3dDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_MIN); 
    //pd3dDevice->SetRenderState(D3DRS_COLORVERTEX, FALSE); 

    MSG msg; 
    while(g_bContinue) 
    { 
     //Clear render region with blue 
     pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0); 

     //before rendering something, you have to call this 
     pd3dDevice->BeginScene(); 

     //rendering of scene objects happens here 

     //begin the effect 
     UINT uiPasses = 0; 
     g_lpEffect->Begin(&uiPasses, 0); 
     for (UINT uiPass = 0; uiPass < uiPasses; uiPass++) 
     { 
      //render an effect pass 
      g_lpEffect->BeginPass(uiPass); 

      //render the rectangle 
      pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); 

      g_lpEffect->EndPass(); 
     } 
     g_lpEffect->End(); 

     //after the scene call 
     pd3dDevice->EndScene(); 

     //update screen = swap front and backbuffer 
     pd3dDevice->Present(NULL, NULL, NULL, NULL); 

     // A window has to handle its messages. 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
     PeekMessage(&msg, 0, 0, 0, PM_REMOVE); 
    } 

頂點數據類型:

//Definition of the Vertex Format including position and diffuse color 
#define D3DFVF_COLOREDVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE) 

struct COLORED_VERTEX 
{ 
    float x, y, z; //Position 
    DWORD color; //Color 
}; 

回答

1

你設置四邊形的頂點的顏色。由頂點形成器輸出的所有信息由光柵化器在三角形的三個頂點之間自動插入以生成片段。這些被傳遞給pixelshader,它只是返回給定的顏色,導致漸變。爲了規避這種行爲,您有兩種可能性:

首先,您可以在pixelshader中分支您的顏色,例如,通過測試紋理座標。

struct VS_OUTPUT 
{ 
    float4 Position : POSITION; 
    float2 Tex: TEXCOORD0; 
}; 

//Vertex Shader 
VS_OUTPUT RenderSceneVS(VSInputTxVc VertexIn) 
{ 
    VS_OUTPUT VertexOut; 
    VertexOut.Position = VertexIn.Position; 
    VertexOut.Tex = VertexIn.TexCoord; 

    return VertexOut; 
} 

//Pixel Shader 
float4 RenderScenePS(float2 Tex: TEXCOORD0) : COLOR 
{ 
    float4 Color = 0; 
    if(Tex.x > 0.5) 
    { 
     Color = float4(1,0,0,1); // Right half-part must have red color 
    } 
    else 
    { 
     Color = float4(0,0,1,1); // Left half-part must have blue color 
    } 
    return Color; 
} 

第二種方法是呈現兩個半全屏四邊形。然後,您可以在頂點中設置顏色,並通過頂點着色器幾乎使用當前的方法。

+0

嗨,我用你的方法與pixelshader,但所有的點都Tex.X = 1.0,代碼://'的Pixel Shader 個float4 RenderScenePS (float2 Tex:TEXCOORD0):COLOR { float4 Color = 0; \t if(Tex.x == 1.0) { Color = float4(1,0,0,1); //右半部分必須有紅色 } 否則 { Color = float4(0,0,1,1); //左半部分必須有藍色 } return Color;全部用紅色填充。我附加了這個項目:spiribit.com/temp/DemoShaderEffect.zip – Jarikus 2014-11-26 22:55:16

+0

啊,我沒有看到你沒有在C++端爲你的頂點設置紋理座標。如果用結構和FVF中的紋理座標替換顏色,它應該可以工作。 – Gnietschow 2014-11-27 10:12:08

+0

Gnietschow>因爲我沒有創建紋理,我決定將「POSITION」轉換爲「TEXCOORD0」:'VertexOut.Tex.x = VertexIn.Position.x + 0.5; VertexOut.Tex.y = VertexIn.Position.y + 0.5;'我做的更新代碼顯示波紋管。非常感謝你。 – Jarikus 2014-11-27 13:25:38

0
後「Gnietschow的言論着色器的

更新代碼:

struct VSInputTxVc 
{ 
    float4 Position : POSITION; 
    float2 TexCoord : TEXCOORD0; 
    float4 Color  : COLOR; 
}; 

struct VS_OUTPUT 
{ 
    float4 Position : POSITION; 
    float2 Tex: TEXCOORD0; 
}; 

//Vertex Shader 
VS_OUTPUT RenderSceneVS(VSInputTxVc VertexIn) 
{ 
    VS_OUTPUT VertexOut; 
    VertexOut.Position = VertexIn.Position; 

    // Convert coordinates from "POSITION" to "TEXCOORD0" 
    // And normalize coordinates from [-1,1] to [0,1] (only for DirectX 9) 
    // Looks like black magic but works fine ;) 
    VertexOut.Tex.x = VertexIn.Position.x + 0.5; 
    VertexOut.Tex.y = VertexIn.Position.y + 0.5; 

    return VertexOut; 
} 

//Pixel Shader 
float4 RenderScenePS(float2 Tex: TEXCOORD0) : COLOR 
{ 
    float4 Color = 0; 

    if(Tex.x > 0.5) 
    { 
     Color = float4(1,0,0,1); // Right half-part must have red color 
    } 
    else 
    { 
     Color = float4(0,0,1,1); // Left half-part must have blue color 
    } 
    return Color; 
} 

technique RenderScene 
{ 
    pass P0 
    { 
     VertexShader = (compile vs_1_1 RenderSceneVS()); 
     PixelShader = (compile ps_2_0 RenderScenePS()); 
    } 
}