Sign in to follow this  
u235

[MDX] Weird flickering going on

Recommended Posts

My terrain rendering application was working perfectly ('pefectly' being a relative term based on phase of development). One day, though, with no changes to the code, the program still works like it was except there is this horrendous flickering and I can't for the life of me figure out what is causing it. The strange part is, I ran my app in PIX and whenever I use F12 to take a screnshot, the screenshot comes out exactly like it should, yet I still get the horrendous flickering. Also, PIX reported an almost constant 60 FPS, so it may have something to do with vsync, but I doubt it. However, if you think it may have something to do with it, I don't know how to turn off vsync so an answer for that would be much appreciated. Thanks for the help. -AJ

Share this post


Link to post
Share on other sites
You can control V-Sync with the PresentParameters.PresentationInterval property. But it is still possible that your GFX driver overrides these settings. It is somewhere in the control panel for your GFX but depends on the model and driver you use.

Share this post


Link to post
Share on other sites
That's right, when creating the D3D device, use

presentParams.PresentationInterval = useVSync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;

to (de)activate vsync.

Share this post


Link to post
Share on other sites
Quote:
Original post by Enselic
How do you render?

I would also recomend that you post as much source as possible.


I apologize, but I didn't think it mattered since it was working and now it doesn't with no changes to the code. I'm not at the computer that has the code on it right now, though, so I will update this post with code as soon as I get home.

As general overview for how I render:

BeginScene();
Process keyboard input for camera movement
Set new view matrix based on keyboard input
SetStreamSource(0, vb, 0);
device.IndexBuffer = ib;
DrawIndexedPrimitives();
EndScene();

I'll post the actual code as well pertinent code ASAP.

-AJ

Share this post


Link to post
Share on other sites
Well the rendering looks totally ok, though maybe you should read keyboard input prior to BeginScene().

These mysterious bugs are the most fun ones [smile].

Share this post


Link to post
Share on other sites
Quote:
Original post by Enselic
These mysterious bugs are the most fun ones [smile].


Indeed [smile]


Quote:
Original post by Sr_Guapo
Are you sure you clearing the depth buffer? If not, it will cause some strange flickering and artifacts.


I'm very sure. That was actually the first thing I checked. The first line of the OnPaint override is:

device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, whatever, other, paramters, this, function, takes);

-AJ

Share this post


Link to post
Share on other sites
Do you render inside the OnPaint method? In this case you have to make sure that you have disabled the background drawing of the control you use. If you don’t do this it can cause flickering between your image and the background that is used to clear the control.

Share this post


Link to post
Share on other sites
Quote:
Original post by Demirug
Do you render inside the OnPaint method? In this case you have to make sure that you have disabled the background drawing of the control you use. If you don’t do this it can cause flickering between your image and the background that is used to clear the control.


Yes, I do render inside the OnPaint method. How do you disable background drawing of the form? Thanks.

-AJ

Share this post


Link to post
Share on other sites
How does it flicker? Every two frame or more like second-long flickers?
Does the flicker seem to be connected to camera movement/orientation?, i.e. does it flicker even if you are not moving anything?

Share this post


Link to post
Share on other sites
Quote:
Original post by Enselic
How does it flicker? Every two frame or more like second-long flickers?
Does the flicker seem to be connected to camera movement/orientation?, i.e. does it flicker even if you are not moving anything?


It's a constant flickering where most of the screen is black and there are horizontal portions that can be seen that flicker constantly and change position/size based on camera movement. Also, I have to play around with camera position/orientation to be able to see anything, but once I am able to see something it flickers regardless of whether the camera is moving or not.

-AJ

Share this post


Link to post
Share on other sites
Quote:
Original post by u235
Quote:
Original post by Demirug
Do you render inside the OnPaint method? In this case you have to make sure that you have disabled the background drawing of the control you use. If you don’t do this it can cause flickering between your image and the background that is used to clear the control.


Yes, I do render inside the OnPaint method. How do you disable background drawing of the form? Thanks.

-AJ



You need to add this code to your control/form class that is used for MDX.

protected override void OnPaintBackground(PaintEventArgs e)
{
}


Share this post


Link to post
Share on other sites
When I enconter directly unidentifiable problems, I usually use this algorithm:

1. Backup the entire project
2. Remove some code
3. Compile and see if the problem is solved, if yes goto 4, if not, goto 2
4. Perform a more detailed analyze of the removed code

This algorithm is very time consuming, but eventually I have always found the code that were wrong.

Share this post


Link to post
Share on other sites
I haven't found the problem yet, but I did find something that may be related. Regardless of the color I clear to, the screen is mostly black and the flickering is in the clear color. When I set PresentationInterval to Immediate, the flickering is much faster and pronounced than if I don't set PresentationInterval at all, which I guess makes sense, but I can't really tell if it's a step in the right direction. Just thought I would give y'all up to the minute info.

-AJ

Share this post


Link to post
Share on other sites
I think your best bet now is to provide as much sourcecode as possible.

You can also check if you get artifacts when running the samples that comes with the DX SDK. If those also have artifacts, it is likely a driver/hardware problem.

Share this post


Link to post
Share on other sites
As much source code as possible? Ok, you asked for it [smile]:

Terrain class(Terrain.cs):

using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;

namespace TerrainGen
{
class Terrain
{
Microsoft.DirectX.DirectInput.Device kb = null;
public int width;
public int height;
private CustomVertex.PositionColored[] vertices;
private int[,] heightData;
public int[] indices;
public IndexBuffer ib;
public VertexBuffer vb;

public void InitializeDevice(System.Windows.Forms.Control window, Camera cam, out Microsoft.DirectX.Direct3D.Device device)
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
presentParams.EnableAutoDepthStencil = true;
presentParams.AutoDepthStencilFormat = DepthFormat.D16;
device = new Microsoft.DirectX.Direct3D.Device(0, Microsoft.DirectX.Direct3D.DeviceType.Hardware, window, CreateFlags.HardwareVertexProcessing, presentParams);
device.SetTransform(TransformType.View, cam.GetViewMatrix());
device.RenderState.FillMode = FillMode.Solid;
device.RenderState.CullMode = Cull.None;
}

public void CameraPositioning(Microsoft.DirectX.Direct3D.Device device, System.Windows.Forms.Control window)
{
device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI/4, window.Width/window.Height, 1f, 300f);
device.Transform.View = Matrix.LookAtLH(new Vector3(0,0,0), new Vector3(), new Vector3(0,1,0));
device.RenderState.Lighting = false;
device.RenderState.CullMode = Cull.None;
}

public void VertexDeclaration(Microsoft.DirectX.Direct3D.Device device)
{
vb = new VertexBuffer(typeof(CustomVertex.PositionColored), width*height, device, Usage.Dynamic | Usage.WriteOnly, CustomVertex.PositionColored.Format, Pool.Default);
vertices = new CustomVertex.PositionColored[width*height];
for (int x=0;x< width;x++)
{
for (int y=0; y< height;y++)
{
vertices[x+y*width].Position = new Vector3(x, y, heightData[x,y]);
if (heightData[x, y] <= 255 && heightData[x, y] >= 120)
{
vertices[x + y * width].Color = Color.WhiteSmoke.ToArgb();
}

if (heightData[x, y] <= 119 && heightData[x, y] >= 85)
{
vertices[x + y * width].Color = Color.SlateGray.ToArgb();
}

if (heightData[x, y] <= 84 && heightData[x, y] >= 36)
{
vertices[x + y * width].Color = Color.LawnGreen.ToArgb();
}

if (heightData[x, y] <= 35)
{
vertices[x + y * width].Color = Color.Brown.ToArgb();
}
}
}

vb.SetData(vertices, 0 , LockFlags.None);
}

public void IndicesDeclaration(Microsoft.DirectX.Direct3D.Device device)
{
ib = new IndexBuffer(typeof(int), (width-1)*(height-1)*6, device, Usage.WriteOnly, Pool.Default);
indices = new int[(width-1)*(height-1)*6];
for (int x=0;x< width-1;x++)
{
for (int y=0; y< height-1;y++)
{
indices[(x+y*(width-1))*6] = (x+1)+(y+1)*width;
indices[(x+y*(width-1))*6+1] = (x+1)+y*width;
indices[(x+y*(width-1))*6+2] = x+y*width;

indices[(x+y*(width-1))*6+3] = (x+1)+(y+1)*width;
indices[(x+y*(width-1))*6+4] = x+y*width;
indices[(x+y*(width-1))*6+5] = x+(y+1)*width;
}
}
ib.SetData(indices, 0, LockFlags.None);
}

public void LoadHeightData(string fileName)
{
StreamReader sr = new StreamReader(fileName);
short x = Int16.Parse(sr.ReadLine());
short y = Int16.Parse(sr.ReadLine());
heightData = new int[x,y];
for (int i = 0;i< y;i++)
{
for (int b=0; b< x; b++)
{
int high = Int32.Parse(sr.ReadLine());
heightData[x-1-b,y-1-i] = high;
}
}
sr.Close();
FileInfo f = new FileInfo(fileName);
f.Delete();
width = x;
height = y;
}

public void InitInput(System.Windows.Forms.Control window)
{
kb = new Microsoft.DirectX.DirectInput.Device(SystemGuid.Keyboard);
kb.SetCooperativeLevel(window, CooperativeLevelFlags.Background | CooperativeLevelFlags.NonExclusive);
kb.Acquire();
}

public void ProcessInput(Camera cam, System.Windows.Forms.Control window)
{
KeyboardState keys = kb.GetCurrentKeyboardState();
if (keys[Key.Up])
cam.Walk(0.5f);
if (keys[Key.Down])
cam.Walk(-0.5f);
if (keys[Key.Left])
cam.Yaw(-0.05f);
if (keys[Key.Right])
cam.Yaw(0.05f);
if (keys[Key.Home])
cam.Pitch(0.05f);
if (keys[Key.End])
cam.Pitch(-0.05f);
if (keys[Key.Escape])
window.Dispose();
}
}
}



Form class for using MDX(Visualize.cs):

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX.DirectInput;

namespace TerrainGen
{
public partial class Visualize : Form
{
Terrain terrain = new Terrain();
public Microsoft.DirectX.Direct3D.Device device;
Camera cam = new Camera(Camera.CameraType.AIRCRAFT);

public Visualize()
{
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
}

private void Visualize_Load(object sender, EventArgs e)
{
terrain.InitializeDevice(this, cam, out device);
terrain.LoadHeightData("temp.lot");
terrain.InitInput(this);
terrain.CameraPositioning(device, this);
terrain.VertexDeclaration(device);
terrain.IndicesDeclaration(device);
}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.SkyBlue , 1.0f, 0);
terrain.ProcessInput(cam, this);
device.BeginScene();
device.SetTransform(TransformType.View, cam.GetViewMatrix());
device.VertexFormat = CustomVertex.PositionColored.Format;
device.SetStreamSource(0, terrain.vb, 0);
device.Indices = terrain.ib;


device.Transform.World = Matrix.Translation(-terrain.height / 2, -terrain.width / 2, 0);
device.Transform.World = Matrix.RotationX((float)(-90.0f * Math.PI) / 180.0f);
device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, terrain.width * terrain.height, 0, terrain.indices.Length / 3);
device.EndScene();

device.Present();

this.Invalidate();
}

protected override void OnPaintBackground(PaintEventArgs e)
{
}
}
}




Camera class(Camera.cs):

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Threading;
using System.Windows.Forms;
using Microsoft;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace TerrainGen
{
class Camera
{
public enum CameraType
{
LANDOBJ,
AIRCRAFT
}

public CameraType cameraType;
public Vector3 right;
public Vector3 up;
public Vector3 look;
public Vector3 pos;

public Camera()
{
cameraType = CameraType.LANDOBJ;
pos = new Vector3(0.0f, 0.0f, -5.0f);
look = new Vector3(.0f, 0.0f, 1.0f);
up = new Vector3(0.0f, 1.0f, 0.0f);
right = new Vector3(1.0f, 0.0f, 0.0f);
}

public Camera(CameraType CT)
{
cameraType = CT;
pos = new Vector3(0.0f, 0.0f, -5.0f);
look = new Vector3(0.0f, 0.0f, 1.0f);
up = new Vector3(0.0f, 1.0f, 0.0f);
right = new Vector3(1.0f, 0.0f, 0.0f);
}

public void Strafe(float units)
{
if (cameraType == CameraType.LANDOBJ)
pos += new Vector3(right.X, 0.0f, right.Z) * units;
if (cameraType == CameraType.AIRCRAFT)
pos += right * units;
}

public void Fly(float units)
{
if (cameraType == CameraType.AIRCRAFT)
pos += up * units;
}

public void Walk(float units)
{
if (cameraType == CameraType.LANDOBJ)
pos += new Vector3(look.X, 0.0f, look.Z) * units;
if (cameraType == CameraType.AIRCRAFT)
pos += look * units;
}

public void Pitch(float angle)
{
Matrix T = Matrix.RotationAxis(right, angle);

up = Vector3.TransformCoordinate(up, T);
look = Vector3.TransformCoordinate(look, T);
}

public void Yaw(float angle)
{
Matrix T;

if (cameraType == CameraType.LANDOBJ)
T = Matrix.RotationY(angle);
else if (cameraType == CameraType.AIRCRAFT)
T = Matrix.RotationAxis(up, angle);
else
return;

right = Vector3.TransformCoordinate(right, T);
look = Vector3.TransformCoordinate(look, T);
}

public void Roll(float angle)
{
if (cameraType == CameraType.AIRCRAFT)
{
Matrix T = Matrix.RotationAxis(look, angle);

right = Vector3.TransformCoordinate(right, T);
up = Vector3.TransformCoordinate(up, T);
}
}

public Matrix GetViewMatrix()
{
Matrix v;

look = Vector3.Normalize(look);

up = Vector3.Cross(look, right);
up = Vector3.Normalize(up);

right = Vector3.Cross(up, look);

float x = -Vector3.Dot(right, pos);
float y = -Vector3.Dot(up, pos);
float z = -Vector3.Dot(look, pos);

v.M11 = right.X;
v.M12 = up.X;
v.M13 = look.X;
v.M14 = 0.0f;

v.M21 = right.Y;
v.M22 = up.Y;
v.M23 = look.Y;
v.M24 = 0.0f;

v.M31 = right.Z;
v.M32 = up.Z;
v.M33 = look.Z;
v.M34 = 0.0f;

v.M41 = x;
v.M42 = y;
v.M43 = z;
v.M44 = 1.0f;

return v;
}

public void SetCameraType(CameraType CT)
{
cameraType = CT;
}

public Vector3 GetPosition()
{
return pos;
}

public void SetPosition(Vector3 Position)
{
pos = Position;
}

public Vector3 GetRight()
{
return right;
}

public Vector3 GetUp()
{
return up;
}

public Vector3 GetLook()
{
return look;
}
}
}




I apologize that it's not commented, but I am about to have to leave for work. If you need comments, let me know and I will add them. This is all the code that I use for the particular form that uses MDX. There's more, but it's not relevent because it's for a seperate form that works perfectly for now. Thanks for all the help.

-AJ

Share this post


Link to post
Share on other sites
Now here is something absolutely mind boggling. I created a new project, just for shits and giggles to see what would happen. Anyone care to take a guess as to what happened? You guessed it, it ran perfectly. Absolutely no change in the code, none whatsoever. I'm as dumbfounded as I'm sure y'all are.

-AJ

Share this post


Link to post
Share on other sites
Quote:
Original post by u235
Now here is something absolutely mind boggling. I created a new project, just for shits and giggles to see what would happen. Anyone care to take a guess as to what happened? You guessed it, it ran perfectly. Absolutely no change in the code, none whatsoever. I'm as dumbfounded as I'm sure y'all are.

-AJ


That is strange... Did you set the form to not draw outside of the OnPaint? In the form's constructor, add this line:

this.Setstyle(Controlstyles.AllPaintingInWmPaint, true);


That should ensure that windows isn't trying to be smart and draw over your window.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sr_Guapo
Quote:
Original post by u235
Now here is something absolutely mind boggling. I created a new project, just for shits and giggles to see what would happen. Anyone care to take a guess as to what happened? You guessed it, it ran perfectly. Absolutely no change in the code, none whatsoever. I'm as dumbfounded as I'm sure y'all are.

-AJ


That is strange... Did you set the form to not draw outside of the OnPaint? In the form's constructor, add this line:

this.Setstyle(Controlstyles.AllPaintingInWmPaint, true);


That should ensure that windows isn't trying to be smart and draw over your window.


I had it that way in the original [sad], but thanks for the suggesstion. I'm very tempted to just shrug my shoulders and continue development on the new project. But I want to figure this out. It started as a challenging bug to find, which it still is, but the inexplicableness of it coupled with the fact that a new project using the exact same code runs prefectly is really starting to piss me off.

-AJ

Share this post


Link to post
Share on other sites
Well, from what I gather from the docs, that also shouldn't work, so maybe you just got lucky with the new project. Anyway, assuming you are still using

this.Setstyle(Controlstyles.AllPaintingInWmPaint | Controlstyles.Opaque, true);

in you visualize class, I think I might have found something. According to the (.NET 2.0) docs the AllPaintingInWmPaint bit should only be applied if the UserPaint bit is set to true as well. According to the docs, the UserPaint bit does the following:

Quote:
If true, the control paints itself rather than the operating system doing so. If false, the Paint event is not raised. This style only applies to classes derived from Control.


This sounds like it will help in your case, though at first glance it might mess up any OnPaint/Invalidate render loops. IIRC the samples from Tom Miller's Kickstart book also used this flag though, so it might not be an issue. If it is, you could always switch to the OnIdle/AppStillIdle loop.

Hope this helps :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this