【问题标题】:Size limitation when using a texture as a render target使用纹理作为渲染目标时的大小限制
【发布时间】:2012-08-17 19:46:31
【问题描述】:

我想创建一个纹理并渲染到它的表面,但我有一个问题:当纹理尺寸太大(超过 263x263 像素 ARGB)时,表面上没有渲染图元(我只能看到颜色在清除操作期间使用)。

这是我的代码:

    private void Form1_Load(object sender, EventArgs e)
    {
        // Setting up DirectX
        PresentParameters pp = new PresentParameters()
        {
            BackBufferCount = 1,
            Windowed = true,
            SwapEffect = SwapEffect.Discard,
            BackBufferWidth = ClientSize.Width,
            BackBufferHeight = ClientSize.Height,
        };

        d3d = new Direct3D();
        device = new Device(d3d, 0, DeviceType.Hardware, Handle, CreateFlags.HardwareVertexProcessing, pp);

        TexturedVertex.SetVertexDeclaration(device);

        // Creating a triangle
        triangleBuffer = new VertexBuffer(device, 3 * Marshal.SizeOf(typeof(TexturedVertex)), Usage.WriteOnly, VertexFormat.None, Pool.Managed);

        var stream1 = triangleBuffer.Lock(0, 0, LockFlags.None);
        stream1.WriteRange(new[] {
                            new TexturedVertex( -2, -2, 0, 0, 0 ),
                            new TexturedVertex( 0, 2, 0, 1, 0),
                            new TexturedVertex( 2, -2, 0, 1, 1),
                    });

        triangleBuffer.Unlock();

        // Creating a rect
        rectBuffer = new VertexBuffer(device, 4 * Marshal.SizeOf(typeof(TexturedVertex)), Usage.WriteOnly, VertexFormat.None, Pool.Managed);

        var stream2 = rectBuffer.Lock(0, 0, LockFlags.None);
        stream2.WriteRange(new[] {
                            new TexturedVertex( -2, -2, 0, 0, 0 ),
                            new TexturedVertex( -2, 2, 0, 0, 1),
                            new TexturedVertex( 2, -2, 0, 1, 0),
                            new TexturedVertex( 2, 2, 0, 1, 1),
                    });

        TexturedVertex.SetVertexDeclaration(device);
        rectBuffer.Unlock();

        // Creating a render texture
        int w = 262;
        Texture texture = new Texture(device, w, w, 0, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);

        Surface surface = texture.GetSurfaceLevel(0);
        Surface buffer = device.GetRenderTarget(0);

        device.SetRenderTarget(0, surface);

        device.SetTransform(TransformState.Projection, Matrix.OrthoOffCenterLH(-4, 4, -4, 4, 0, 100));
        device.SetTransform(TransformState.View, Matrix.Identity);
        device.SetTransform(TransformState.World, Matrix.Identity);

        device.Clear(ClearFlags.Target, new Color4(Color.Green), 0, 0);

        device.BeginScene();

        device.SetStreamSource(0, triangleBuffer, 0, Marshal.SizeOf(typeof(TexturedVertex)));
        device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 3);

        device.EndScene();
        device.Present();

        device.SetRenderTarget(0, buffer);

        // Setting current texture and material
        device.SetTexture(0, texture);
        Material mat = new Material();
        mat.Ambient = mat.Diffuse = mat.Emissive = Color.White;
        device.Material = mat;

        // Setting the projection, view and transform matrix
        device.SetTransform(TransformState.Projection, Matrix.OrthoOffCenterLH(-4, 4, -4, 4, 0, 100));
        device.SetTransform(TransformState.View, Matrix.Identity);
        device.SetTransform(TransformState.World, Matrix.Identity);


        // Setting handler
        this.KeyDown += new KeyEventHandler(Form1_KeyDown);
        this.Paint += new PaintEventHandler(Form1_Paint);
    }

    void Form1_Paint(object sender, PaintEventArgs e)
    {
        device.Clear(ClearFlags.Target, new Color4(Color.Purple), 0, 0);

        device.BeginScene();

        device.SetStreamSource(0, rectBuffer, 0, Marshal.SizeOf(typeof(TexturedVertex)));
        //device.SetStreamSource(0, triangleBuffer, 0, Marshal.SizeOf(typeof(TexturedVertex)));

        device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 4);

        device.EndScene();

        device.Present();
    }

【问题讨论】:

    标签: c# directx slimdx


    【解决方案1】:

    我猜你的表单的客户端大小是 262 像素宽或高。

    在显示参数中,您将后台缓冲区和 z 缓冲区限制为该大小。您需要另一个 Z 缓冲区,与您要渲染的纹理大小相匹配,并且您需要将其设置为使用,然后切换回原来的。

    Surface oldDepthBuffer = device.DepthStencilSurface;
    Texture db = new Texture(device, w, w, 1, Usage.DepthStencil, oldDepthBuffer.Description.Format, Pool.Default);
    
    Surface myDepthBuffer = db.GetSurfaceLevel(0);
    
    device.SetRenderTarget(0, surface);
    device.DepthStencilSurface = myDepthBuffer;
    
    // RENDER to texture
    
    device.DepthStencilSurface = oldDepthBuffer;
    

    【讨论】:

    • 我找到了另一种方法:删除我不使用的 z 缓冲区就可以了:pp.EnableAutoDepthStencil = false
    • 我尝试了您的编辑,它也可以工作:我可以继续使用 z 缓冲区,谢谢!!
    • 我最终得到了您的解决方案,因为在绘制图元时禁用深度缓冲区会降低多重采样质量(我不知道为什么......)
    • 多重采样不是对整个图像进行过采样,它首先检查子像素的深度是否与其他子像素不同,如果是,则从它们中提取多个样本。如果没有深度缓冲区,它可能无法检查深度差异并且无法获得多个样本,因此会造成质量损失。
    猜你喜欢
    • 2020-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-20
    • 2018-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多