RenderTargetBitmap 和 Viewport3D - 质量问题 [英] RenderTargetBitmap and Viewport3D - Quality Issues

查看:34
本文介绍了RenderTargetBitmap 和 Viewport3D - 质量问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将 3D 场景从 Viewport3D 导出​​到位图.

I'm wanting to export a 3D scene from a Viewport3D to a bitmap.

最明显的方法是使用 RenderTargetBitmap -- 但是当我这样做时,导出的位图的质量明显低于屏幕图像.网上查了一下,RenderTargetBitmap好像没有利用硬件渲染.这意味着渲染是在 第 0 层 完成的.这意味着没有 mip-mapping 等,因此导出图像的质量降低.

The obvious way to do this would be to use RenderTargetBitmap -- however when I this the quality of the exported bitmap is significantly lower than the on-screen image. Looking around on the internet, it seems that RenderTargetBitmap doesn't take advantage of hardware rendering. Which means that the rendering is done at Tier 0. Which means no mip-mapping etc, hence the reduced quality of the exported image.

有人知道如何以屏幕质量导出 Viewport3D 的位图吗?

Does anyone know how to export a bitmap of a Viewport3D at on-screen quality?

澄清

虽然下面给出的例子没有显示这一点,我最终需要将 Viewport3D 的位图导出到一个文件中.据我所知,唯一的方法是将图像放入从 BitmapSource 派生的东西.下面的 Cplotts 显示使用 RenderTargetBitmap 提高导出质量可以改善图像,但由于渲染仍然在软件中完成,所以速度非常慢.

Though the example given below doesn't show this, I need to eventually export the bitmap of the Viewport3D to a file. As I understand the only way to do this is to get the image into something that derives from BitmapSource. Cplotts below shows that increasing the quality of the export using RenderTargetBitmap improves the image, but as the rendering is still done in software, it is prohibitively slow.

有没有办法使用硬件渲染将渲染的 3D 场景导出到文件中?这应该可行吗?

你可以看到这个 xaml 的问题:

You can see the problem with this xaml:

<Window x:Class="RenderTargetBitmapProblem.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="400" Width="500">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Viewport3D Name="viewport3D">
            <Viewport3D.Camera>
                <PerspectiveCamera Position="0,0,3"/>
            </Viewport3D.Camera>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <AmbientLight Color="White"/>
                </ModelVisual3D.Content>
            </ModelVisual3D>
            <ModelVisual3D>
                <ModelVisual3D.Content>
                    <GeometryModel3D>
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D Positions="-1,-10,0  1,-10,0  -1,20,0  1,20,0"
                                            TextureCoordinates="0,1 0,0 1,1 1,0"
                                            TriangleIndices="0,1,2 1,3,2"/>
                        </GeometryModel3D.Geometry>
                        <GeometryModel3D.Material>
                            <DiffuseMaterial>
                                <DiffuseMaterial.Brush>
                                    <ImageBrush ImageSource="http://www.wyrmcorp.com/galleries/illusions/Hermann%20Grid.png"
                                                TileMode="Tile" Viewport="0,0,0.25,0.25"/>
                                </DiffuseMaterial.Brush>
                            </DiffuseMaterial>
                        </GeometryModel3D.Material>
                    </GeometryModel3D>
                </ModelVisual3D.Content>
                <ModelVisual3D.Transform>
                    <RotateTransform3D>
                        <RotateTransform3D.Rotation>
                            <AxisAngleRotation3D Axis="1,0,0" Angle="-82"/>
                        </RotateTransform3D.Rotation>
                    </RotateTransform3D>
                </ModelVisual3D.Transform>
            </ModelVisual3D>
        </Viewport3D>
        <Image Name="rtbImage" Visibility="Collapsed"/>
        <Button Grid.Row="1" Click="Button_Click">RenderTargetBitmap!</Button>
    </Grid>
</Window>

还有这段代码:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        RenderTargetBitmap bmp = new RenderTargetBitmap((int)viewport3D.ActualWidth, 
            (int)viewport3D.ActualHeight, 96, 96, PixelFormats.Default);
        bmp.Render(viewport3D);
        rtbImage.Source = bmp;
        viewport3D.Visibility = Visibility.Collapsed;
        rtbImage.Visibility = Visibility.Visible;
    }

推荐答案

RenderTargetBitmap 上没有设置告诉它使用硬件渲染,所以你将不得不回退到使用 Win32 或 DirectX.我建议使用 本文 中给出的 DirectX 技术.文章中的以下代码并展示了如何完成(这是 C++ 代码):

There is no setting on RenderTargetBitmap to tell it to render using hardware, so you will have to fall back to using Win32 or DirectX. I would recommend using the DirectX technique given in this article. The following code from the article and shows how it can be done (this is C++ code):

extern IDirect3DDevice9* g_pd3dDevice;
Void CaptureScreen()
{
    IDirect3DSurface9* pSurface;
    g_pd3dDevice->CreateOffscreenPlainSurface(ScreenWidth, ScreenHeight,
        D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &pSurface, NULL);
    g_pd3dDevice->GetFrontBufferData(0, pSurface);
    D3DXSaveSurfaceToFile("Desktop.bmp",D3DXIFF_BMP,pSurface,NULL,NULL);
    pSurface->Release(); 
}

您可以创建与 WPF 内容正在呈现的位置对应的 Direct3D 设备,如下所示:

You can create the Direct3D device corresponding to the place where the WPF content is being rendered as follows:

  1. 在屏幕图像中的一个点上调用 Visual.PointToScreen
  2. User32.dll中调用MonitorFromPoint获取hMonitor
  3. d3d9.dll中调用Direct3DCreate9得到一个pD3D
  4. 调用 pD3D->GetAdapterCount() 来计算适配器数量
  5. 从0迭代到count-1并调用pD3D->GetAdapterMonitor()并与之前检索到的hMonitor进行比较以确定适配器索引
  6. 调用 pD3D->CreateDevice() 来创建设备本身
  1. Calling Visual.PointToScreen on a point within your onscreen image
  2. Calling MonitorFromPoint in User32.dll to get the hMonitor
  3. Calling Direct3DCreate9 in d3d9.dll to get a pD3D
  4. Calling pD3D->GetAdapterCount() to count adapters
  5. Iterating from 0 to count-1 and calling pD3D->GetAdapterMonitor() and comparing with the previously retrieved hMonitor to determine the adapter index
  6. Calling pD3D->CreateDevice() to create the device itself

我可能会在用 C++/CLR 编码的单独库中完成大部分工作,因为我对这种方法很熟悉,但您可能会发现使用 SlimDX.我还没试过.

I would probably do most of this in a separate library coded in C++/CLR because that approach is familiar to me, but you may find it easy to translate it to pure C# and managed code using using SlimDX. I haven't tried that yet.

这篇关于RenderTargetBitmap 和 Viewport3D - 质量问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆