2

我正在屏幕外创建一个 Viewport3D (CurViewport3D) 并仅用一个平面填充它(用于测试目的)。

通过 RenderTargetBitmap 和 BitmapEncoder 创建此视口内容(作为 jpg)的 MemoryStream。整个功能都放在一个库 (dll) 中,因为我想在 Web 服务器上使用这个库来创建一个要在网站上显示的图像。

下面的代码被简化为基础,但它正在工作。

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;
using System.Windows.Controls;
using System.Windows.Threading;

namespace RenderTargetImage_Test
{
    public class RenderTargetImage01
    {
        public System.IO.MemoryStream stream = new System.IO.MemoryStream();
        Int32 width = 100;
        Int32 height = 100;
        Viewport3D CurViewport3D;

        public RenderTargetImage01()
        {
            CurViewport3D = new Viewport3D();
            Model3DGroup myModel3DGroup = new Model3DGroup();
            ModelVisual3D myModelVisual3D = new ModelVisual3D(); 

            PerspectiveCamera myPCamera = new PerspectiveCamera();
            myPCamera.Position = new Point3D(3500, 1500, -5000);
            myPCamera.LookDirection = new Vector3D(-0.5, 0, 1);
            myPCamera.FieldOfView = 70;
            CurViewport3D.Camera = myPCamera;

            AmbientLight myAmbientLight = new AmbientLight();
            myAmbientLight.Color = Colors.White;
            myModel3DGroup.Children.Add(myAmbientLight);

            MeshGeometry3D meshS2 = new MeshGeometry3D();
            GeometryModel3D modelS2 = new GeometryModel3D();

            meshS2.Positions.Add(new Point3D(500, 500, -500));
            meshS2.Positions.Add(new Point3D(500, 3000, -500));
            meshS2.Positions.Add(new Point3D(3000, 500, -500));
            meshS2.Positions.Add(new Point3D(3000, 3000, -500));
            meshS2.TriangleIndices.Add(0);
            meshS2.TriangleIndices.Add(1);
            meshS2.TriangleIndices.Add(2);
            meshS2.TriangleIndices.Add(3);
            meshS2.TriangleIndices.Add(2);
            meshS2.TriangleIndices.Add(1);
            meshS2.Normals.Add(new Vector3D(0, 0, 1));
            meshS2.Normals.Add(new Vector3D(0, 0, 1));
            meshS2.Normals.Add(new Vector3D(0, 0, 1));
            meshS2.Normals.Add(new Vector3D(0, 0, 1));
            meshS2.Normals.Add(new Vector3D(0, 0, 1));
            meshS2.Normals.Add(new Vector3D(0, 0, 1));
            meshS2.TextureCoordinates.Add(new System.Windows.Point(0, 0));
            meshS2.TextureCoordinates.Add(new System.Windows.Point(1, 0));
            meshS2.TextureCoordinates.Add(new System.Windows.Point(0, 1));
            meshS2.TextureCoordinates.Add(new System.Windows.Point(1, 1));

            modelS2.Geometry = meshS2;
            DiffuseMaterial DiffMS2 = new DiffuseMaterial(System.Windows.Media.Brushes.Red);
            modelS2.Material = DiffMS2;
            myModel3DGroup.Children.Add(modelS2);
            myModelVisual3D.Content = myModel3DGroup;
            CurViewport3D.Children.Add(myModelVisual3D);

            // render
            RenderTargetBitmap renderTargetBitmap = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
            CurViewport3D.Width = width;
            CurViewport3D.Height = height;
            CurViewport3D.Measure(new System.Windows.Size(width, height));
            CurViewport3D.Arrange(new Rect(0, 0, width, height));
            CurViewport3D.Dispatcher.Invoke(((Action)(() => renderTargetBitmap.Render(CurViewport3D))), DispatcherPriority.Render);
            BitmapEncoder bitmapEncoder = new PngBitmapEncoder();
            bitmapEncoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
            bitmapEncoder.Save(stream);
        }
    }
}

这是网站的代码:

<body>
    <form id="form1" runat="server">
    <div>
    </div>
    </form>
</body>

以及背后的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using System.Windows.Shapes;

using System.Windows.Media;
using System.Windows.Media.Imaging;

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;

using RenderTargetImage_Test;

public partial class Default2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        RenderTargetImage01 rti = new RenderTargetImage01();

        rti.stream.WriteTo(Response.OutputStream);
        Response.ContentType = "image/png";
        Response.Flush();
        Response.End();
    }
}

很简单!

现在的问题是:本地一切正常。图像显示在浏览器中 - 完美。一旦我尝试在 Web 服务器(Microsoft Server 2008)上运行它,浏览器中显示的图像是空的,没有内容。没有错误。

有谁知道如何让它在网络服务器上运行?

4

3 回答 3

1

答案很简单:WPF 3D 渲染在Session 0 Isolation中不起作用,适用于 WIndows 2008 服务器及更高版本(或客户端中的 Vista/Seven)下的非交互式用户。 我没有找到任何真正解决同一问题的方法,因为所有这些都需要在服务器上(甚至是远程用户)有一个登录用户,该用户在不同于 0 的 Session中托管 WPF 绘图。所以作为一个非常激进的解决方案,我使用 OpenGL 来渲染它:因为 Opengl 可以以纯软件方式渲染,它不受会话 0 的影响,而且它就像一个魅力。

于 2013-03-26T10:28:14.020 回答
0

我尝试了 DirectX9(通过 SharpDX)并且无法在会话 0 隔离中初始化 3d 支持。经过一番调查,我发现这仅适用于 DirectX 11:http: //msdn.microsoft.com/en-us/library/windows/desktop/hh404562%28v=vs.85%29.aspx#use_direct3d_in_session_0_processes

不幸的是,这只适用于 Windows 8 和 Windows Server 2012。

于 2014-03-13T15:52:22.763 回答
-1

好吧,这似乎是一个问题,即在渲染时视口在屏幕外。我相信视口中的结果从未真正呈现到屏幕上。现在由于它在本地工作,问题可能出在服务器上的图形硬件上。虽然在本地您可能拥有渲染所有调用的硬件,但服务器可能正在通过软件渲染所有内容。该软件只会否定任何无法查看的内容,以节省时间和资源。虽然图形硬件仍将渲染所有内容并将其存储在缓冲区中,直到它变得可见。

如果不是这种情况,那么我将不得不说它与您正在运行的内存流有关。是否有任何 100% 的理由必须使用内存流?如果不尝试没有它的解决方案,看看是否能解决问题。

于 2012-09-27T08:01:09.407 回答