I created a simple shader effect, which must paint left-half part is blue color and right-half part is red color. But the transition is not sharp colors and is made with a gradient see picture:
I need to turn off the smooth transition of colors like here:
Shader effect code:
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());
}
}
I draw full-screen primitive { -1,-1 : -1, 1 : 1,-1 : 1,1 } and I play with different Blending modes but it not help.
C++ code:
//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 data type:
//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
};
You're setting the color of the vertices of the quad. All information outputted by the vertexshader is automatically interpolated between the three vertices of a triangle by the rasterizer to generate the fragments. These are passed to the pixelshader, which simply returns the given color leading to the gradient. To circumvent this behaviour, you have 2 possibilities:
First you could branch your color in the pixelshader, e.g. by testing for the texture coordinate.
The second approach is to render two half-full-screen quads. Then you can set the color in the vertices and use almost your current approach via the vertexshader.