Terrible Flickering with Direct3D

movafova

Newcomer
Joined
Jun 1, 2004
Messages
4
I'm making a program with four viewports that each display different angles of the same scene. I'm writing this in C# using MDX and no seems to have tried this. I know the SDK docs say "use multiple swap chains", but I found some C++ code where some just did it with multiple viewports. With that in mind, why does this program flicker so badly?

Code:
namespace CameraPlacer
{
	/// <summary>
	/// Summary description for Form1.
	/// </summary>
	public class MainForm : System.Windows.Forms.Form
	{
		private Microsoft.DirectX.Direct3D.Device DirectDevice;
		private VertexBuffer VertBuf;
		private System.Windows.Forms.Button SubtractCamera;
		private System.Windows.Forms.Button AddCamera;
		private System.Windows.Forms.Panel Buttons;
		private Camera UpperLeft;
		private Camera UpperRight;
		private Camera LowerLeft;
		private Camera LowerRight;
		private ArrayList Cameras = new ArrayList();
		private int Active;
		private float angle = 0.1f;
		private System.Windows.Forms.Panel DrawPanel;
		private Mesh Tea;

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public MainForm()
		{
			
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();
			InitializeGraphics();

			this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque | ControlStyles.UserPaint | 
				ControlStyles.DoubleBuffer, true);
				
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		public void InitializeGraphics()
		{
			// Set our presentation parameters
			PresentParameters presentParams = new PresentParameters();

			presentParams.Windowed = true;
			presentParams.SwapEffect = SwapEffect.Discard;
		    //presentParams.PresentationInterval = PresentInterval.Immediate;
			presentParams.PresentFlag = PresentFlag.DeviceClip;
			
			// Create our device and cameras
			DirectDevice = new Microsoft.DirectX.Direct3D.Device(0, Microsoft.DirectX.Direct3D.DeviceType.Hardware, DrawPanel, CreateFlags.HardwareVertexProcessing, presentParams);
			UpperLeft = new Camera(.035f, 0, 0, 5, 0, presentParams.BackBufferHeight, presentParams.BackBufferWidth);
			UpperRight = new Camera(.035f, 0, 5, 0, 0, presentParams.BackBufferHeight, presentParams.BackBufferWidth);
			LowerLeft = new Camera(.035f, 5, 0, 0, 0, presentParams.BackBufferHeight, presentParams.BackBufferWidth);
			LowerRight = new Camera(.035f, 0, 0, 5, 0, presentParams.BackBufferHeight, presentParams.BackBufferWidth);
			UpperLeft.ProjMatrix = Matrix.PerspectiveFovLH((float)Math.PI / 4, UpperLeft.View.Width / UpperLeft.View.Height, .035f, 5.0f);
			UpperRight.ProjMatrix = Matrix.PerspectiveFovLH((float)Math.PI / 4, UpperLeft.View.Width / UpperLeft.View.Height, .035f, 5.0f);
			LowerLeft.ProjMatrix = Matrix.PerspectiveFovLH((float)Math.PI / 4, UpperLeft.View.Width / UpperLeft.View.Height, .035f, 5.0f);
			UpperLeft.View.X = 0;
			UpperLeft.View.Y = 0;
			UpperRight.View.X = presentParams.BackBufferWidth / 2;
			UpperRight.View.Y = 0;
			LowerLeft.View.X = 0;
			LowerLeft.View.Y = presentParams.BackBufferHeight / 2;
			Cameras.Add(new Camera(.035f, .07f, 0, 0, 0, presentParams.BackBufferHeight, presentParams.BackBufferWidth));
			Active = 0;
			LowerRight = (Camera) Cameras[Active];
            VertBuf = new VertexBuffer(typeof(CustomVertex.PositionColored), 3, DirectDevice, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);
            VertBuf.Created += new EventHandler(this.OnVertexBufferCreate);
			OnVertexBufferCreate(VertBuf, null);
		}

		private void OnVertexBufferCreate(object sender, EventArgs e)
		{
			VertexBuffer buffer = (VertexBuffer)sender;

			CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[3];
			verts[0].SetPosition(new Vector3(0.0f, 1.0f, 1.0f));
			verts[0].Color = System.Drawing.Color.Aqua.ToArgb();
			verts[1].SetPosition(new Vector3(-1.0f, -1.0f, 1.0f));
			verts[1].Color = System.Drawing.Color.Black.ToArgb();
			verts[2].SetPosition(new Vector3(1.0f, -1.0f, 1.0f));
			verts[2].Color = System.Drawing.Color.Purple.ToArgb();

			buffer.SetData(verts, 0, LockFlags.None);
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.SubtractCamera = new System.Windows.Forms.Button();
			this.AddCamera = new System.Windows.Forms.Button();
			this.Buttons = new System.Windows.Forms.Panel();
			this.DrawPanel = new System.Windows.Forms.Panel();
			this.Buttons.SuspendLayout();
			this.SuspendLayout();
			// 
			// SubtractCamera
			// 
			this.SubtractCamera.Location = new System.Drawing.Point(16, 0);
			this.SubtractCamera.Name = "SubtractCamera";
			this.SubtractCamera.Size = new System.Drawing.Size(16, 16);
			this.SubtractCamera.TabIndex = 4;
			this.SubtractCamera.Text = "-";
			this.SubtractCamera.Click += new System.EventHandler(this.SubtractCamera_Click);
			// 
			// AddCamera
			// 
			this.AddCamera.Location = new System.Drawing.Point(0, 0);
			this.AddCamera.Name = "AddCamera";
			this.AddCamera.Size = new System.Drawing.Size(16, 16);
			this.AddCamera.TabIndex = 5;
			this.AddCamera.Text = "+";
			this.AddCamera.Click += new System.EventHandler(this.AddCamera_Click);
			// 
			// Buttons
			// 
			this.Buttons.Controls.Add(this.SubtractCamera);
			this.Buttons.Controls.Add(this.AddCamera);
			this.Buttons.Dock = System.Windows.Forms.DockStyle.Top;
			this.Buttons.Location = new System.Drawing.Point(0, 0);
			this.Buttons.Name = "Buttons";
			this.Buttons.Size = new System.Drawing.Size(1016, 16);
			this.Buttons.TabIndex = 8;
			// 
			// DrawPanel
			// 
			this.DrawPanel.Dock = System.Windows.Forms.DockStyle.Fill;
			this.DrawPanel.Location = new System.Drawing.Point(0, 16);
			this.DrawPanel.Name = "DrawPanel";
			this.DrawPanel.Size = new System.Drawing.Size(1016, 725);
			this.DrawPanel.TabIndex = 9;
			this.DrawPanel.Paint += new System.Windows.Forms.PaintEventHandler(this.DrawPanel_Paint);
			// 
			// MainForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(1016, 741);
			this.Controls.Add(this.DrawPanel);
			this.Controls.Add(this.Buttons);
			this.Name = "MainForm";
			this.Text = "FirstAttempt";
			this.Buttons.ResumeLayout(false);
			this.ResumeLayout(false);

		}
		#endregion

		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main() 
		{
			using (MainForm frm = new MainForm())
			{
				// Show our form and initialize our graphics engine
				frm.Show();
				Application.Run(frm);
			}

		}

		private void AddCamera_Click(object sender, System.EventArgs e)
		{
			Cameras.Add(new Camera(.035f, .07f, 0, 0, 0, DirectDevice.PresentationParameters.BackBufferHeight, 
					   DirectDevice.PresentationParameters.BackBufferWidth));
		}

		private void SubtractCamera_Click(object sender, System.EventArgs e)
		{
			if (Cameras.Count > 1)
                Cameras.RemoveAt(Active);
		}

		private void DrawPanel_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
		{
			LowerRight = (Camera) Cameras[Active];
			DirectDevice.Transform.World = Matrix.RotationAxis(new Vector3(angle / ((float)Math.PI * 2.0f), angle / ((float)Math.PI * 4.0f), angle / ((float)Math.PI * 6.0f)),  angle / (float)Math.PI);
			DirectDevice.RenderState.CullMode = Cull.None;
			angle += 0.1f;
			DirectDevice.RenderState.Lighting = false;
			DirectDevice.VertexFormat = CustomVertex.PositionColored.Format;
			DirectDevice.SetStreamSource(0, VertBuf, 0);
			
			DirectDevice.Viewport = UpperLeft.View;
			DirectDevice.Clear(ClearFlags.Target, System.Drawing.Color.Red, 1.0f, 0);
			DirectDevice.Transform.Projection = UpperLeft.ProjMatrix;
			DirectDevice.Transform.View = Matrix.LookAtLH(UpperLeft.Location, new Vector3(), new Vector3(0,1,0));
			DirectDevice.BeginScene();
			DirectDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
			DirectDevice.EndScene();
			DirectDevice.Present();

			DirectDevice.Viewport = UpperRight.View;
			DirectDevice.Clear(ClearFlags.Target, System.Drawing.Color.CornflowerBlue, 1.0f, 0);
			DirectDevice.Transform.Projection = UpperRight.ProjMatrix;
			DirectDevice.Transform.View = Matrix.LookAtLH(UpperRight.Location, new Vector3(), new Vector3(0,1,0));
			DirectDevice.BeginScene();
			DirectDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
			DirectDevice.EndScene();
			DirectDevice.Present();

			DirectDevice.Viewport = LowerLeft.View;
			DirectDevice.Clear(ClearFlags.Target, System.Drawing.Color.Green, 1.0f, 0);
			DirectDevice.Transform.Projection = LowerLeft.ProjMatrix;
			DirectDevice.Transform.View = Matrix.LookAtLH(LowerLeft.Location, new Vector3(), new Vector3(0,1,0));
			DirectDevice.BeginScene();
			DirectDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
			DirectDevice.EndScene();
			DirectDevice.Present();
			
			DirectDevice.Viewport = LowerRight.View;
			DirectDevice.Clear(ClearFlags.Target, System.Drawing.Color.Gray, 1.0f, 0);
			DirectDevice.Transform.Projection = LowerRight.ProjMatrix;
			DirectDevice.Transform.View = Matrix.LookAtLH(LowerRight.Location, new Vector3(), new Vector3(0,1,0));
			DirectDevice.BeginScene();
			DirectDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
			DirectDevice.EndScene();
			DirectDevice.Present();
			
			DrawPanel.Invalidate();
		}
	}
}
 
Flickering is usually caused by trying to render each frame onto the front buffer, a possible solution is to use a back buffer, this is called double buffering.
 
I'm new to all this... so is that harder than just setting the style of the window to ControlStyles.DoubleBuffer? I already did that, and it didn't seem to affect the flickering at all.
 
Oh yeah, I also should mention that I'm drawing inside a panel, not there entire window... how do you setstyle for a panel?
 
I am not a C# programmer so i'm not too sure about the c# add-on stuff. But
from reading your codes i think you are missing a few lines to initialise the back buffer format, height and width.

presentParams.BackBufferHeight = HERE YOU PUT THE DISPLAY HEIGHT
presentParams.BackBufferWidth = HERE YOU PUT THE DISPLAY WIDTH
presentParams.BackBufferFormat = HERE YOU PUT THE DISPLAY FORMAT

hope this will help ~ let me know.
 
also,
you need to lock the vertex buffer before setting the vertices and remember to unlock them when you're done

private void OnVertexBufferCreate(object sender, EventArgs e)
{
VertexBuffer buffer = (VertexBuffer)sender;

CustomVertex.PositionColored[] verts = new CustomVertex.PositionColored[3];

buffer.lock(0,0) = verts[] //sry dude i dont remember the actual syntax of the command
verts[0].SetPosition(new Vector3(0.0f, 1.0f, 1.0f));
verts[0].Color = System.Drawing.Color.Aqua.ToArgb();
verts[1].SetPosition(new Vector3(-1.0f, -1.0f, 1.0f));
verts[1].Color = System.Drawing.Color.Black.ToArgb();
verts[2].SetPosition(new Vector3(1.0f, -1.0f, 1.0f));
verts[2].Color = System.Drawing.Color.Purple.ToArgb();
buffer.unlock;

// buffer.SetData(verts, 0, LockFlags.None); //not too sure what this line does(its in your code above)
}
 
Back
Top