⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 renderwindow.cs

📁 游戏编程精粹6的光盘源代码
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing.Imaging;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Reflection;
using System.IO;
using System.Threading;

namespace BilevelTextureMagnification
{
	/// <summary>
	/// Non-modal 3D preview window
	/// </summary>
	public class RenderWindow : System.Windows.Forms.Form
	{
		private System.ComponentModel.Container components = null;

		private Texture optimizedTexture, hiResTexture;
		private Device myDevice;
		private VertexBuffer myVertexBuffer;
		private Effect myEffect;
		private VertexDeclaration myVertexDeclaration;
		private RenderWindowThread myThread;
		private double time = 0.0;

		private System.Windows.Forms.MenuItem viewMenu;
		private System.Windows.Forms.MenuItem viewInputMenuItem;
		private System.Windows.Forms.MenuItem viewOutputMenuItem;
		private System.Windows.Forms.MenuItem viewThresholdedMenuItem;
		private System.Windows.Forms.MenuItem animateMenu;
		private System.Windows.Forms.MenuItem animateOnMenuItem;
		private System.Windows.Forms.MainMenu mainMenu;

		internal static RenderWindow Create()
		{
			RenderWindowThread t = new RenderWindowThread();
			return t.Window;
		}

		private class RenderWindowThread
		{
			private RenderWindow window;
			private bool isReady = false;
			private Thread t;

			public RenderWindowThread()
			{
				t = new Thread(new ThreadStart(start));
				t.Priority = ThreadPriority.Lowest;
				t.Start();
			}

			private void start()
			{
				window = new RenderWindow(this);
				isReady = true;
				Application.Run(window);
			}

			public RenderWindow Window
			{
				get
				{
					while(!isReady || !window.Created)
					{
						Thread.Sleep(10);
					}
					return window;
				}
			}

			public void Kill()
			{
				window.Close();
				t.Join();
			}
		}

		internal void Kill()
		{
			myThread.Kill();
		}

		private RenderWindow(RenderWindowThread t)
		{
			myThread = t;

			InitializeComponent();
			SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);

			PresentParameters presentationParameters = new PresentParameters();
			presentationParameters.Windowed = true;
			presentationParameters.SwapEffect = SwapEffect.Discard;

			DeviceType dt = DeviceType.Hardware;
			if(Manager.GetDeviceCaps(0, DeviceType.Hardware).PixelShaderVersion.Major < 3)
			{
				dt = DeviceType.Reference;
				Text += " (emulated in SW)";
			}
			myDevice = new Device(0, dt, this, CreateFlags.HardwareVertexProcessing, presentationParameters);

			// gamma-correct rendering
			myDevice.RenderState.SrgbWriteEnable = true;

			Assembly assem = Assembly.GetAssembly(typeof(RenderWindow));
			Stream st = assem.GetManifestResourceStream("BilievelTextureMagnification.Shader.fx");

			myEffect = Effect.FromStream(myDevice, st, null, null, ShaderFlags.None, null);
			st.Close();
			st = null;
			myEffect.Technique = "threshold";
			
			VertexElement[] vertexElements = new VertexElement[]
				{
					new VertexElement(0, 0, DeclarationType.Float3, DeclarationMethod.Default, DeclarationUsage.Position, 0),
					new VertexElement(0, 3*4, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0),
					new VertexElement(0, 5*4, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 1),
					VertexElement.VertexDeclarationEnd
			};
			myVertexDeclaration = new VertexDeclaration(myDevice, vertexElements);
		}

		internal void SetBaseTexture(int[,] optimizedArray, Bitmap hiResBitmap)
		{
			lock(this)
			{
				if(optimizedTexture != null)
				{
					optimizedTexture.Dispose();
					optimizedTexture = null;
				}

				if(hiResTexture != null)
				{
					hiResTexture.Dispose();
					hiResTexture = null;
				}
				if(hiResTexture == null)
				{
					// The obvious solution would be:
					// hiResTexture = new Texture(myDevice, hiResBitmap, Usage.AutoGenerateMipMap, Pool.Managed);
					// But that doesn't work for reading.
					
					int wHi = hiResBitmap.Width;
					int hHi = hiResBitmap.Height;
					int maxMipLevel = (int)(1.5 + Math.Log(Math.Min(wHi, hHi), 2.0));

					hiResTexture = new Texture(myDevice, wHi, hHi, maxMipLevel, Usage.None, Format.L8, Pool.Managed);
					byte[,] hiResTextureArray = (byte[,])hiResTexture.LockRectangle(typeof(byte), 0, LockFlags.None, new int[]{hHi, wHi});
					for(int j = 0; j < hHi; j++)
					{
						for(int i = 0; i < wHi; i++)
						{
							hiResTextureArray[j, i] = hiResBitmap.GetPixel(i, j).R;
						}
					}
					hiResTexture.UnlockRectangle(0);
					TextureLoader.FilterTexture(hiResTexture, 0, Filter.Box);
				}

				int w = optimizedArray.GetLength(1);
				int h = optimizedArray.GetLength(0);

				int downsampling = hiResTexture.GetLevelDescription(0).Width / w;
				int levelOffset = (int)(0.5 + Math.Log(downsampling, 2.0));
				optimizedTexture = new Texture(myDevice, w, h, hiResTexture.LevelCount - levelOffset, 0, Format.L8, Pool.Managed);

				// skip the first level; that's filled dynamically
				for(int level = 1; level < hiResTexture.LevelCount - levelOffset; level++)
				{
					int scale = (int)(0.5 + Math.Pow(2.0, level));

					byte[,] originalTextureArray = (byte[,])hiResTexture.LockRectangle(typeof(byte), level + levelOffset, LockFlags.ReadOnly, new int[]{h/scale, w/scale});
					byte[,] optimizedTextureArray = (byte[,])optimizedTexture.LockRectangle(typeof(byte), level, LockFlags.None, new int[]{h/scale, w/scale});
					
					int wLevel = w / scale;
					int hLevel = h / scale;

					for(int j = 0; j < hLevel; j++)
					{
						for(int i = 0; i < wLevel; i++)
						{
							int x = optimizedTextureArray[j, i];

							optimizedTextureArray[j, i] = (byte)originalTextureArray[j, i];
						}
					}

					optimizedTexture.UnlockRectangle(level);
					hiResTexture.UnlockRectangle(level + levelOffset);
				}

				if(myVertexBuffer != null)
				{
					myVertexBuffer.Dispose();
				}

				myVertexBuffer = new VertexBuffer(typeof(DualTextureVertex), 4, myDevice, Usage.WriteOnly, 0, Pool.Managed);
				DualTextureVertex[] myVertexData = new DualTextureVertex[4];
				float aspectRatio = h/(float)w;
				myVertexData[0] = new DualTextureVertex(-1.0f,  aspectRatio, 0.0f, 0.0f, 0.0f, 0, 0);
				myVertexData[1] = new DualTextureVertex(-1.0f, -aspectRatio, 0.0f, 0.0f, 1.0f, 0, h);
				myVertexData[2] = new DualTextureVertex( 1.0f,  aspectRatio, 0.0f, 1.0f, 0.0f, w, 0);
				myVertexData[3] = new DualTextureVertex( 1.0f, -aspectRatio, 0.0f, 1.0f, 1.0f, w, h);
				myVertexBuffer.SetData(myVertexData, 0, LockFlags.None);
			}
		}
		
		internal void SetTexture(int[,] optimizedArray, Bitmap hiResBitmap)
		{
			lock(this)
			{
				if(optimizedTexture == null || optimizedTexture.Disposed)
				{
					return; // something went wrong
				}

				int w = optimizedArray.GetLength(1);
				int h = optimizedArray.GetLength(0);

				SurfaceDescription sd = optimizedTexture.GetLevelDescription(0);
				if(w != sd.Width || h != sd.Height) // Out-of-date texture? (Didn't call SetBaseTexture first?)
				{
					return;
				}

				byte[,] optimizedtextureArray = (byte[,])optimizedTexture.LockRectangle(typeof(byte), 0, LockFlags.None, new int[]{h, w});
				int wLevel = optimizedtextureArray.GetLength(1);
				int hLevel = optimizedtextureArray.GetLength(0);
				for(int j = 0; j < hLevel; j++)
				{
					for(int i = 0; i < wLevel; i++)
					{
						optimizedtextureArray[j, i] = (byte)(optimizedArray[j, i]);
					}
				}
				optimizedTexture.UnlockRectangle(0);
			}
		}

		internal void SaveTexture(string fileName)
		{
			lock(this)
			{
				TextureLoader.Save(fileName, ImageFileFormat.Dds, optimizedTexture);
			}
		}

		// Called by RenderWindowThread. Don't call from somewhere else.
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
		{
			lock(this)
			{
				if(myDevice == null || myVertexBuffer == null)
				{
					return;
				}

				else if(animateOnMenuItem.Checked)
				{
					time += 0.5; // in theory, this does _not_ work indefinitely long
				}

				// float s = (float)(3.0 + 2.95*Math.Sin(1.4+0.2941*time));
				myDevice.Transform.World =
					//Matrix.Scaling(s, s, s) *
					  Matrix.RotationX((float)(0.9*Math.Sin(0.3+0.3175*time)))
					* Matrix.RotationY((float)(0.9*Math.Sin(0.2+0.2923*time)))
					* Matrix.RotationZ((float)(0.7*Math.Sin(0.1+0.2843*time)))
					* Matrix.Translation((float)(0.2*Math.Sin(0.3423*time)), (float)(0.2*Math.Sin(0.2712*time)), (float)(11.0-11.0*Math.Sin(0.2737*time)));

				myDevice.Clear(ClearFlags.Target, Color.LightBlue, 1.0f, 0);
				myDevice.BeginScene();

				myDevice.Transform.Projection = Matrix.PerspectiveFovLH(0.3f, ClientSize.Width/(float)((ClientSize.Height != 0) ? ClientSize.Height : 1), 0.01f, 100.0f);
				myDevice.Transform.View = Matrix.LookAtLH(new Vector3(0.0f, 0.0f, -2.0f), new Vector3(), new Vector3(0.0f, 1.0f, 0.0f));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -