2012-05-07 29 views
2

我在屏幕外創建一個Viewport3D(CurViewport3D)並僅用一個平面填充(用於測試目的)。wpf在Web服務器上的Viewport3D的RenderTargetBitmap(離屏)

通過RenderTargetBitmap和BitmapEncoder創建此視口內容的MemoryStream(如jpg)。整個功能都放在一個庫(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)上運行它,瀏覽器中顯示的圖像是空的,沒有內容。沒有錯誤。

有誰知道如何讓它在網絡服務器上運行?

回答

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的影響,並且它像魅力一樣起作用。

+0

看來你是完全正確的。但是,你能告訴我如何使用OpenGL呈現WPF視口嗎?你爲什麼把它命名爲一個徹底的解決方案? – manton

+0

因爲你完全放棄了WPF而鬱鬱蔥蔥,只是使用OpenGL(我使用SharpGL)來渲染你的場景。我的方案非常簡單 - 一個三維多高餅圖 - 我能夠通過反轉z-coord來重用所有網格。過程並不複雜,但很難,也可能是OT。 –

-1

嗯這似乎是一個事實,即視口在渲染時是離屏的。我相信在視口中的結果永遠不會被渲染到屏幕上。現在,由於它在本地工作,問題可能在於服務器上的圖形硬件。在本地你可能有硬件來渲染所有被調用的東西,服務器可能通過軟件渲染所有東西。該軟件只會否定任何無法查看的時間和資源。雖然圖形硬件仍然可以渲染所有內容並將其存儲在緩衝區中,直到它變爲可查看爲止。

如果情況並非如此,那麼我將不得不說它與你正在運行的內存流有關。有沒有100%的理由需要使用內存流?如果不嘗試沒有它的解決方案,看看是否解決了這個問題。

相關問題