using System; using System.Collections.Generic; using System.Collections; using System.Text; using Microsoft.DirectX; using Microsoft.DirectX.Direct3D; using System.Windows.Forms; using System.Drawing; using System.Runtime.InteropServices; using System.IO; using System.Drawing.Imaging; namespace TextureTools { // 纹理合并工具,利用离屏渲染,将若干张纹理渲染到一张纹理上 public class TextureMerger { private TextureMerger() { // 初始化 D3D 设备 if (!D3DHelper.InitGraphics()) { return; } m_d3dDevice = D3DHelper.D3DDevice; if(D3DHelper.CheckDeviceState() == false) { if(D3DHelper.ResetDevice() == false) { return; } } Init(); } // 请在get Instance之前调用 public static bool SetShaderPath(String strShaderPath) { if(strShaderPath == null) { return false; } m_strShaderPath = strShaderPath; return true; } public static bool SetTextureSize(int iSize) { if(iSize <= 0) { return false; } m_iTargetSize = iSize; return true; } public static TextureMerger Instance { get { if(ms_Instance == null) { ms_Instance = new TextureMerger(); } return ms_Instance; } } // 初始化资源 private bool Init() { if(D3DHelper.CheckDeviceState() == false) { return false; } if (!CreateRT(m_iTargetSize)) { return false; } if (!CreateQuad()) { return false; } if (!CreateEffect()) { return false; } return true; } public void Dispose() { ClearBitMaps(); if(m_BGTexture != null) { m_BGTexture.Dispose(); m_BGTexture = null; } ClearRT(); if (m_RetrivedTexture != null) { m_RetrivedTexture.Dispose(); m_RetrivedTexture = null; } if(m_Effect != null) { m_Effect.Dispose(); } ms_Instance = null; // Export time stap [5/18/2009 hemeng] //SaveTimeToFile(@"TimeStamp.log"); //m_TimeStamp.Clear(); } protected void ClearRT() { if (m_RTTexture0 != null) { m_RTTexture0.Dispose(); m_RTTexture0 = null; } if (m_RTTexture1 != null) { m_RTTexture1.Dispose(); m_RTTexture1 = null; } if(m_RetrivedTexture != null) { m_RetrivedTexture.Dispose(); m_RetrivedTexture = null; } } // 渲染到 RT public void Render(System.Drawing.Image targetBitmap) { if(D3DHelper.CheckDeviceState() == false) { // add [5/31/2009 hemeng] // 如果设备丢失,则reset设备 if(D3DHelper.ResetDevice() == false) { return; } // 由新设备重新创建RT ClearRT(); if (CreateRT(m_iTargetSize) == false) { return; } m_vbQuad = null; if(CreateQuad() == false ) { return; } } if ( m_RTTexture0 == null || m_vbQuad == null) { return; } Surface oldRT = m_d3dDevice.GetRenderTarget(0); m_d3dDevice.SetRenderTarget(0, m_RTTexture0.GetSurfaceLevel(0)); m_bLastRT = true; m_d3dDevice.Clear(ClearFlags.Target, Color.Black, 1.0f, 0); m_d3dDevice.BeginScene(); m_d3dDevice.SetStreamSource(0, m_vbQuad, 0); m_d3dDevice.VertexFormat = CustomVertex.TransformedTextured.Format; // Shader渲染 Draw(); m_d3dDevice.EndScene(); RetriveRenderTarget(targetBitmap); m_d3dDevice.SetRenderTarget(0, oldRT); } // 添加一个位图 public void AddBitMap(Image bitmap, float fAlpha) { if (bitmap != null) { Texture texture = null; using (MemoryStream mmStream = new MemoryStream()) { bitmap.Save(mmStream, ImageFormat.Bmp); mmStream.Seek(0, SeekOrigin.Begin); texture = TextureLoader.FromStream(m_d3dDevice, mmStream); mmStream.Close(); mmStream.Dispose(); } if (texture != null) { m_SrcTextures.Add(texture); m_SrcAlpha.Add(fAlpha); } } } public void AddBitMap(String strFilePath, float fAlpha) { if (strFilePath != null) { Texture texture = TextureLoader.FromFile(m_d3dDevice, strFilePath); if (texture != null) { m_SrcTextures.Add(texture); m_SrcAlpha.Add(fAlpha); } } } // 清除图片 public void ClearBitMaps() { for (int i = 0; i < m_SrcTextures.Count; i++) { Texture temp = (Texture)m_SrcTextures[i]; temp.Dispose(); m_SrcTextures[i] = null; m_SrcAlpha[i] = null; } m_SrcTextures.Clear(); m_SrcAlpha.Clear(); } // 设置背景 public void SetBGBitMap(Bitmap bitmap) { if (bitmap != null) { Texture texture = null; using (MemoryStream mmStream = new MemoryStream()) { bitmap.Save(mmStream, ImageFormat.Bmp); mmStream.Seek(0,SeekOrigin.Begin); texture = TextureLoader.FromStream(m_d3dDevice, mmStream); mmStream.Close(); mmStream.Dispose(); } if(texture != null) { m_BGTexture = texture; } } } [DllImport("gdi32.dll")] private static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, Int32 dwrop); private bool RetriveRenderTarget(System.Drawing.Image targetBitmap) { if(D3DHelper.CheckDeviceState() == false) { return false; } if (targetBitmap == null) { return false; } try { // 首先取得 render target 数据到 targetSrc Surface targetSur = m_RetrivedTexture.GetSurfaceLevel(0); Surface rtSur = m_d3dDevice.GetRenderTarget(0); if(rtSur == null || targetSur == null) { return false; } m_d3dDevice.GetRenderTargetData(rtSur, targetSur); // 使用 BitBlt 拷贝 hdc 的内容 Graphics target = Graphics.FromImage(targetBitmap); Graphics src = targetSur.GetGraphics(); IntPtr iTarget = target.GetHdc(); IntPtr iSrc = src.GetHdc(); BitBlt(iTarget, 0, 0, targetBitmap.Width, targetBitmap.Height ,iSrc , 0, 0, 13369376); target.ReleaseHdc(iTarget); src.ReleaseHdc(iSrc); targetSur.ReleaseGraphics(); return true; } catch (Exception e) { MessageBox.Show(e.ToString()); return false; } } // 创建作为 render target 的 texture protected bool CreateRT(int iTexSize) { if (D3DHelper.CheckDeviceState() == false) { return false; } try { if(m_RTTexture0 == null) m_RTTexture0 = new Texture(m_d3dDevice, iTexSize, iTexSize, 1, Usage.RenderTarget, Format.X8R8G8B8, Pool.Default); if(m_RTTexture1 == null) m_RTTexture1 = new Texture(m_d3dDevice, iTexSize, iTexSize, 1, Usage.RenderTarget, Format.X8R8G8B8, Pool.Default); if(m_RetrivedTexture == null) m_RetrivedTexture = new Texture(m_d3dDevice, iTexSize, iTexSize, 1, Usage.None, Format.X8R8G8B8, Pool.SystemMemory); return true; } catch (Exception e) { MessageBox.Show(e.ToString()); return false; } } protected bool CreateQuad() { if (D3DHelper.CheckDeviceState() == false) { return false; } try { // 创建 VB CustomVertex.TransformedTextured[] quad = new CustomVertex.TransformedTextured[4]; quad[0] = new CustomVertex.TransformedTextured(0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); quad[1] = new CustomVertex.TransformedTextured((float)m_iTargetSize, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f); quad[2] = new CustomVertex.TransformedTextured(0.0f, (float)m_iTargetSize, 0.0f, 1.0f, 0.0f, 1.0f); quad[3] = new CustomVertex.TransformedTextured((float)m_iTargetSize, (float)m_iTargetSize, 0.0f, 1.0f, 1.0f, 1.0f); m_vbQuad = new VertexBuffer(typeof(CustomVertex.TransformedTextured) , 4, m_d3dDevice, Usage.WriteOnly, CustomVertex.TransformedTextured.Format, Pool.Default); m_vbQuad.SetData(quad, 0, LockFlags.None); return true; } catch (Exception e) { MessageBox.Show(e.ToString()); return false; } } protected bool CreateEffect() { if (D3DHelper.CheckDeviceState() == false) { return false; } try { // test only // 创建 Effect m_ePool = new EffectPool(); // (Device device, string sourceDataFile, Include includeFile, string skipConstants, ShaderFlags flags, EffectPool pool); m_Effect = Effect.FromFile(m_d3dDevice, m_strShaderPath, null, null, ShaderFlags.None, m_ePool); m_Effect.Technique = "TestShader"; return true; } catch (Exception e) { MessageBox.Show(e.ToString()); return false; } } // effect draw [5/11/2009 hemeng] protected void Draw() { // Add Time Stap [5/18/2009 hemeng] //AddTimeStamp("Enter Draw"); // end if (D3DHelper.CheckDeviceState() == false) { return; } if(m_Effect == null) { return; } m_Effect.SetValue("fColorKey", m_TransColor); m_Effect.SetValue("fTextureWidth", (float)m_iTargetSize); // shader每次采样8层纹理,背景固定为RT,每次混合纹理7张 int iNumPass = m_SrcTextures.Count / 7; int iRestPass = m_SrcTextures.Count % 7; m_Effect.Begin(0); // 首先处理7整数层纹理条件部分 for (int i = 0; i < iNumPass; i++) { // 计算当前处理层 int iTexIndex = i * 7; // 如果当前RT为m_RTTexture1,则以m_RTTexture0为RT,反之以m_RTTexture1为RT if(m_bLastRT == false) { // 重新设置设备RT m_d3dDevice.SetRenderTarget(0, m_RTTexture0.GetSurfaceLevel(0)); // 首先将之前处理的rt作为最底层 m_Effect.SetValue("Texture0", m_RTTexture1); m_bLastRT = true; } else { m_d3dDevice.SetRenderTarget(0, m_RTTexture1.GetSurfaceLevel(0)); m_Effect.SetValue("Texture0", m_RTTexture0); m_bLastRT = false; } for (int j = 0; j < 7; j++ ) { m_Effect.SetValue("Texture"+(j+1).ToString("G"), (Texture)m_SrcTextures[iTexIndex+j]); m_Effect.SetValue("fAlpha"+(j + 1).ToString("G"), (float)m_SrcAlpha[iTexIndex+j]); } m_Effect.BeginPass(0); m_d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); m_Effect.EndPass(); } // 其次处理余数层纹理 if (iRestPass != 0) { Texture baseTex = null; int iRepeat = 8 - iRestPass; if (m_bLastRT == true) { m_d3dDevice.SetRenderTarget(0, m_RTTexture1.GetSurfaceLevel(0)); m_bLastRT = false; baseTex = m_RTTexture0; } else { m_d3dDevice.SetRenderTarget(0, m_RTTexture0.GetSurfaceLevel(0)); m_bLastRT = true; baseTex = m_RTTexture1; } for (int i = 0; i < iRepeat; i++) { m_Effect.SetValue("Texture" + i.ToString("G"), baseTex); } for (int i = 0; i < iRestPass; i++) { m_Effect.SetValue("Texture" + (iRepeat + i).ToString("G"), (Texture)m_SrcTextures[iNumPass * 7 + i]); m_Effect.SetValue("fAlpha" + (iRepeat + i).ToString("G"), (float)m_SrcAlpha[iNumPass * 7 + i]); } m_Effect.BeginPass(0); m_d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2); m_Effect.EndPass(); baseTex = null; } m_Effect.End(); //AddTimeStamp("Quit Draw"); } //public void AddTimeStamp(String msg) //{ // DateTime dt = System.DateTime.Now; // String strTimeStame = String.Concat(dt.Minute.ToString(), " : ", dt.Second.ToString()); // strTimeStame = String.Concat(strTimeStame, " : ", dt.Millisecond.ToString()); // strTimeStame = String.Concat(strTimeStame, " - ", msg); // strTimeStame = String.Concat(strTimeStame, "\r\n"); // //Console::Write(strTimeStame); // //m_TimeStamp.Add(strTimeStame); //} //private bool SaveTimeToFile(String strFilePath) //{ // if(strFilePath == null) // { // return false; // } // using (StreamWriter sw = new StreamWriter(strFilePath)) // { // for (int i = 0; i < m_TimeStamp.Count; i++) // { // sw.WriteLine((String)m_TimeStamp[i]); // } // } // return true; //} protected Effect m_Effect = null; // protected Texture m_RTTexture0 = null; // First Render Target // 添加用于交换渲染的RenderTargt [5/7/2009 hemeng] protected Texture m_RTTexture1 = null; // Second Render Target protected Texture m_RetrivedTexture = null; protected VertexBuffer m_vbQuad = null; // protected ColorValue m_TransColor = new ColorValue(0, 0, 0); // 透明色, 默认为黑色 protected ArrayList m_SrcTextures = new ArrayList(); // 源纹理 protected ArrayList m_SrcAlpha = new ArrayList(); // 源纹理的alpha值 protected Texture m_BGTexture = null; protected Device m_d3dDevice = null; protected EffectPool m_ePool = null; // 用于标志最后一个渲染RT是否为m_RTTexture0 protected bool m_bLastRT = true; protected static int m_iTargetSize = 1024; // 目标纹理尺寸 protected static String m_strShaderPath = @"Data\Shader\shader.fx"; protected static TextureMerger ms_Instance = null; // 时间戳 [5/18/2009 hemeng] //protected ArrayList m_TimeStamp = new ArrayList(); } }