Direct3D 9效果值在通话中混合使用

时间:2018-06-27 20:44:56

标签: c# direct3d hlsl sharpdx direct3d9

我正尝试通过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();
    }

0 个答案:

没有答案