读取DirectX模板像素值

时间:2017-12-26 10:26:17

标签: unity3d graphics 3d directx direct3d

我们可以使用以下方法成功读取深度缓冲区值。我们如何修改它来代替读取模板值?

感谢。

    byte[] ReadDepthPixels(RenderContextBase context, Texture2D other, System.Drawing.Rectangle rect)
    {
        var depthTex = new D3DTextureDepth(context, other);

        var depths = D3DTexture2D.ReadDepthsInternal(rect, (Texture2D)depthTex.texture);
        var rgbValues = new byte[rect.Width * rect.Height * 4];

        double ratio = 255.0 / short.MaxValue;
        int w = ((Texture2D)depthTex.texture).Description.Width;
        int h = ((Texture2D)depthTex.texture).Description.Height;
        int offset = w - rect.Width;
        int pxlIndex = rect.Y * w + rect.X;
        int count = 0;

        for (int i = 0; i < rect.Height; i++)
        {
            pxlIndex = (h - i - 1) * w; // flip in Y
            for (int j = 0; j < rect.Width; j++, pxlIndex++)
            {
                double val = ratio * depths[pxlIndex];
                rgbValues[count++] = (byte)val;
                rgbValues[count++] = (byte)val;
                rgbValues[count++] = (byte)val;
                rgbValues[count++] = 255;
            }
        }

        depthTex.Dispose();

        return rgbValues;
    }

    short[] ReadDepthsInternal(Rectangle rect, Texture2D texture)
    {
        short[] values = null;

        using (Surface surface = texture.QueryInterface<Surface>())
        {
            int bytesPerElement = 4;
            DataStream dataStream;
            var map = surface.Map(SharpDX.DXGI.MapFlags.Read, out dataStream);
            values = new short[rect.Width*rect.Height];

            int actualWidth = rect.Width*bytesPerElement;

            byte[] rowBytes = new byte[actualWidth];

            int rowDiffBytes = map.Pitch - actualWidth;

            int endY = rect.Y + rect.Height;

            dataStream.Seek(rect.Y*map.Pitch + rect.X*bytesPerElement, SeekOrigin.Begin);

            if (texture.Description.Format == Format.D24_UNorm_S8_UInt)
            {
                int[] intValues = new int[rect.Width];

                float den = (float) Math.Pow(2, 24) - 1; // 16777215

                // Convert from 24 bit depth to 16 bit depth
                float ratio = (float) short.MaxValue/den;

                for (int i = rect.Y, countRow = 0; i < endY; i++, countRow++)
                {
                    dataStream.Read(rowBytes, 0, actualWidth);

                    System.Buffer.BlockCopy(rowBytes, 0, intValues, 0, actualWidth);

                    // REVERSE the read of the depth buffer lines
                    int count = rect.Size.Width*(rect.Size.Height - countRow - 1);

                    for (int j = 0; j < intValues.Length; j++)

                        values[count++] = (short) Math.Round(ratio*intValues[j]);

                    if ((dataStream.Position + rowDiffBytes) <= dataStream.Length)

                        dataStream.Seek(rowDiffBytes, SeekOrigin.Current);
                }
            }              

            dataStream.Dispose();

            surface.Unmap();
        }

        return values;
    }

1 个答案:

答案 0 :(得分:1)

由于我还没有真正试过这个问题,所以完全披露了,但你可以尝试使用DXGI_FORMAT_X24_TYPELESS_G8_UINT格式创建深度/模板纹理的资源视图;这将使您可以访问G8_UINT组件进行阅读。