我创建了一个简单的着色器效果,它必须绘制左半部分为蓝色,右半部分为红色。但过渡不是鲜明的颜色,而是用渐变看到图片:
我需要关闭这里颜色的平滑过渡:
着色器效果代码:
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
};
答案 0 :(得分:1)
您正在设置四边形顶点的颜色。由光栅化器在三角形的三个顶点之间自动插入由顶点着色器输出的所有信息以生成片段。这些传递给像素着色器,它只返回导致渐变的给定颜色。为了避免这种行为,你有两种可能性:
首先,您可以在pixelhader中分支颜色,例如通过测试纹理坐标。
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;
}
第二种方法是渲染两个半全屏四边形。然后你可以设置顶点的颜色,并通过顶点着色器使用几乎你当前的方法。
答案 1 :(得分:0)
在Gnietschow&#39;之后更新着色器的代码。备注:
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());
}
}