我在屏幕外创建一个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)上运行它,浏览器中显示的图像为空,没有内容。没错。
有谁知道如何让它在网络服务器上运行?
答案 0 :(得分:1)
答案非常简单:WPF 3D渲染在Session 0 Isolation中不起作用,适用于WIndows 2008服务器及以上版本的非交互式用户(或客户端中的Vista / Seven)。 I did not find any real solution to the same problem,因为所有这些都需要在服务器(甚至是远程用户)上登录用户,这些用户在不同于0的会话中承载WPF绘图。 因此,作为一个非常彻底的解决方案,我使用OpenGL来呈现相同的内容:由于Opengl可以以纯软件方式呈现,因此它不受会话0的影响,并且它就像魅力一样。
答案 1 :(得分: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。
答案 2 :(得分:-1)
那么在渲染时视口是离屏的这一事实似乎是一个问题。我相信Viewport中的结果实际上从未实际呈现在屏幕上。现在,因为它在本地工作,问题可能在于服务器上的图形硬件。虽然本地可能有硬件来渲染所有被调用的东西,但服务器可能通过软件渲染所有内容。该软件只会否定任何无法查看时间和资源的信息。虽然图形硬件仍然会渲染所有内容并将其存储在缓冲区中,直到它变为可查看状态。
如果不是这种情况,那么我将不得不说它与您运行的内存流有关。有没有100%的理由你必须使用内存流?如果没有它,请尝试解决方案,看看是否能解决问题。