我正尝试通过D3D9效果通过DirectX C#包装器SharpDX绘制一个矩形。下面的代码对于绘制一个矩形效果很好:
single rectangle drawing - red rectangle/lime border
但是,当我绘制多个矩形时,颜色会混合在一起:
dual rectangle drawing - red rectangle/lime border + blue rectangle/white border
我已经在Google上搜索了此问题的解决方案,但无济于事,因为这是D3D9效果的一种相当小众的用法。我怀疑问题是由于传递给效果的值在两个函数调用中混合在一起,因此颜色,屏幕空间位置和尺寸是错误的。
以下是我如何调用渲染函数的代码:
private static void OnEndScene()
{
RectangleRendering.Render(new Vector2(215f, 400f), 500f, 100f, Color.Lime, 5f, Color.Red);
RectangleRendering.Render(new Vector2(300f, 300f), 500f, 100f, Color.Blue, 5f, Color.White);
}
这是渲染循环的代码(RectangleRendering.Render):
public static void Render(
Vector2 screenPosition,
float width,
float height,
Color color,
float borderWidth,
Color borderColor)
{
// Check if the effect is disposed
if (Effect.IsDisposed)
{
return;
}
// Save the current VertexDecleration for restoring later
var decleration = Renderer.Direct3DDevice.VertexDeclaration;
// Begin the shading process
Effect.Begin();
// Lock and write the vertices onto the vertex buffer
VertexBuffer.Lock(0, Utilities.SizeOf<Vector4>() * 4, LockFlags.None).
WriteRange(new[]
{
new Vector4(screenPosition.X, screenPosition.Y + height, 1, 1), // bottom left
new Vector4(screenPosition.X, screenPosition.Y, 1, 1), // top left
new Vector4(screenPosition.X + width, screenPosition.Y + height, 1, 1), // top right
new Vector4(screenPosition.X + width, screenPosition.Y, 1, 1), // bottom right
});
VertexBuffer.Unlock();
// Send all the global variables to the shader
Effect.BeginPass(0);
Effect.SetValue("Transform", Matrix.OrthoOffCenterLH(0, Renderer.ScreenResolutionX, Renderer.ScreenResolutionY, 0, -1, 1));
Effect.SetValue("Color", new Vector4(color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f));
Effect.SetValue("Width", width);
Effect.SetValue("Height", height);
Effect.SetValue("BorderWidth", borderWidth);
Effect.SetValue("BorderColor", new Vector4(borderColor.R / 255f, borderColor.G / 255f, borderColor.B / 255f, borderColor.A / 255f));
Effect.SetValue("ScreenPosition", screenPosition);
Effect.EndPass();
// Send data to the GPU using the Direct3DDevice
Renderer.Direct3DDevice.SetStreamSource(0, VertexBuffer, 0, Utilities.SizeOf<Vector4>());
Renderer.Direct3DDevice.VertexDeclaration = VertexDeclaration;
// Draw the primitives in the shader
Renderer.Direct3DDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
// End the shading process
Effect.End();
// Restore the previous VertexDecleration
Renderer.Direct3DDevice.VertexDeclaration = decleration;
}
以下是效果初始化代码(包括HLSL着色器):
private static void Initialize()
{
// Initialize the vertex buffer, specifying its size, usage, format and pool
VertexBuffer = new VertexBuffer(
Renderer.Direct3DDevice,
Utilities.SizeOf<Vector4>() * 4,
Usage.WriteOnly,
VertexFormat.None,
Pool.Managed);
// Specify the vertex elements to be used by the shader
VertexElements = new[]
{
new VertexElement(
0,
0,
DeclarationType.Float4,
DeclarationMethod.Default,
DeclarationUsage.Position,
0),
VertexElement.VertexDeclarationEnd
};
// Initialize the vertex decleration using the previously created vertex elements
VertexDeclaration = new VertexDeclaration(Renderer.Direct3DDevice, VertexElements);
#region Effect binary
var compiledEffect = new byte[]
{
};
const string effectSource = @"
struct VS_OUTPUT
{
float4 Position : POSITION;
float4 Color : COLOR0;
float4 Position2D : TEXCOORD0;
};
// Globals passed
float4 Color;
float4x4 Transform;
float Width;
float Height;
float BorderWidth;
float4 BorderColor;
float2 ScreenPosition; // top left corner
// Vertex Shader
VS_OUTPUT VS(VS_OUTPUT input)
{
VS_OUTPUT output = (VS_OUTPUT) 0;
output.Position = mul(input.Position, Transform);
output.Color = input.Color;
output.Position2D = input.Position;
return output;
}
// Pixel Shader
float4 PS(VS_OUTPUT input) : COLOR
{
VS_OUTPUT output = (VS_OUTPUT) 0;
output = input;
if (BorderWidth > 0) {
float xl = ScreenPosition.x;
float xr = xl + Width;
float yt = ScreenPosition.y;
float yb = yt + Height;
float4 pos = output.Position2D;
float cx = pos.x;
float cy = pos.y;
// left side
if (cx < xl + BorderWidth) {
return BorderColor;
}
// right side
if (cx > xr - BorderWidth) {
return BorderColor;
}
// top side
if (cy < yt + BorderWidth) {
return BorderColor;
}
// bottom side
if (cy > yb - BorderWidth) {
return BorderColor;
}
}
return Color;
}
technique Main
{
pass P0
{
ZEnable = FALSE;
AlphaBlendEnable = TRUE;
DestBlend = INVSRCALPHA;
SrcBlend = SRCALPHA;
VertexShader = compile vs_2_0 VS();
PixelShader = compile ps_2_0 PS();
}
}";
#endregion
// Load the effect from memory
//Effect = Effect.FromMemory(Renderer.Direct3DDevice, compiledEffect, ShaderFlags.None);
Effect = Effect.FromString(Renderer.Direct3DDevice, effectSource, ShaderFlags.None);
// Set the only technique in the shaders
Technique = Effect.GetTechnique(0);
// Listen to events
AppDomain.CurrentDomain.DomainUnload += (sender, args) => Dispose();
AppDomain.CurrentDomain.ProcessExit += (sender, args) => Dispose();
Renderer.OnReset += args => Effect?.OnLostDevice();
Renderer.OnPostReset += args => Effect?.OnResetDevice();
}