2014-11-25 7 views
0

Я создал простой шейдерный эффект, который должен рисовать левую половину - синий цвет, а правая половина - красного цвета. Но переход не резкие цвета и сделан с уклоном см фото: enter image description hereDirectX 9 + Shader Effect: отключить плавный переход цвета

мне нужно выключить плавный переход цветов, как здесь: 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); 
    } 

Vertex Тип данных:

//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

Вы устанавливаете цвет вершин четырехугольника. Вся информация, выводимая vertexshader, автоматически интерполируется между тремя вершинами треугольника растеризатором для генерации фрагментов. Они передаются в пиксельный элемент, который просто возвращает заданный цвет, ведущий к градиенту. Чтобы обойти это поведение, у вас есть 2 возможности:

Сначала вы можете разветвить свой цвет в пикселях, например. путем тестирования для координаты текстуры.

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; 
} 

Второй подход заключается в рендеринге двух полу-полноразмерных квадроциклов. Затем вы можете установить цвет в вершинах и использовать почти ваш текущий подход через vertexshader.

+0

Привет, я использую свой метод с PixelShader, но все точки имеют Tex.X = 1,0, и код: '// Pixel Shader Float4 RenderScenePS (float2 Tex: TEXCOORD0): ЦВЕТ { float4 Цвет = 0; \t if (Tex.x == 1.0) { Цвет = float4 (1,0,0,1); // Правая половина должна иметь красный цвет } else { Цвет = float4 (0,0,1,1); // Левая половина должна иметь синий цвет } цвет; } 'заполните все красным цветом. Я приложил проект: spiribit.com/temp/DemoShaderEffect.zip – Jarikus

+0

Ах, я не видел, что вы не задали texturecoordinates для своих вершин на стороне C++. Если вы замените цвет координатами текстуры в своей структуре и FVF, он должен работать. – Gnietschow

+0

Gnietschow> Поскольку я не создаю текстуру, я решил преобразовать «POSITION» в «TEXCOORD0»: «VertexOut.Tex.x = VertexIn.Position.x + 0.5; VertexOut.Tex.y = VertexIn.Position.y + 0.5; 'код обновления, который я показал ниже. Большое спасибо. – Jarikus

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()); 
    } 
}