To be honest there isn't any, but i found an old graphical effect which i had
coded which suffered from the same problems. I hoisted all for-loop variables
and the performance increase was truly impressive. I'll give you the code
whole code for the class, just cut'n paste
// --- Field.cs
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Threading;
namespace Field
{
public unsafe sealed class Field : System.Windows.Forms.Form
{
private const int MAXAMP=20, MINAMP=5;
private System.ComponentModel.Container components = null;
private Graphics _hDC;
private Bitmap _buffer;
private int _numPixelsInbuffer;
private int _bufferWidth, _bufferHeight;
private uint [] _palette;
private int [] _hBaseMap, _hRunnerMap;
private Thread _runner;
private bool _done;
public Field()
{
InitializeComponent();
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint
| ControlStyles.Opaque, 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 );
}
/// <summary>
/// Generates a heightmap
/// </summary>
/// <param name="map">Map to generate</param>
private void generateHeightMap(ref int [] map, int minamp, int maxamp)
{
Random r = new Random();
int [] xBaseSine = new int[_bufferWidth];
double freqX = r.Next((_bufferWidth-10)/5)+10;
int amplitudeX = r.Next(maxamp-minamp)+minamp;
double freqY = r.Next((_bufferHeight-10)/5)+10;
int amplitudeY = r.Next(maxamp-minamp)+minamp;
fixed (int* pMap = map, pBase = xBaseSine)
{
int* pM = pMap;
int* pB = pBase;
for (int x = 0; x < _bufferWidth; x++ )
{
*pB = (int)(Math.Sin(x/freqX)*amplitudeX);
pB++;
}
for ( int y = 0; y < _bufferHeight; y++ )
{
pB = pBase;
int yBaseSine = (int)(Math.Sin(y/freqY)*amplitudeY);
for ( int x = 0; x < _bufferWidth; x++ )
{
*pM = yBaseSine+*pB;
pM++; pB++;
}
}
}
}
/// <summary>
/// Initializes our palette with shades of blue
/// </summary>
private uint[] initializePalette(int size)
{
uint[] palette = new uint[size];
double blueDecrPrStep = 255f/size;
for (int i = 0; i < size; i++)
palette
= 0xFF000000 | (byte)(255f-i*blueDecrPrStep);
return palette;
}
private void run()
{
const int FADE=1, ZEROPOINT = 2*MAXAMP;
bool regenerate = true;
int[] tmpArrayPointer;
_palette = initializePalette(4*MAXAMP);
_hRunnerMap = new int[_numPixelsInbuffer];
_hBaseMap = new int[_numPixelsInbuffer];
generateHeightMap(ref _hRunnerMap, MINAMP, MAXAMP);
while(!_done)
{
if (regenerate)
{
tmpArrayPointer = _hBaseMap;
_hBaseMap = _hRunnerMap;
_hRunnerMap = tmpArrayPointer;
generateHeightMap(ref _hRunnerMap, MINAMP, MAXAMP);
}
regenerate = true;
fixed (int* pBaseMap = _hBaseMap, pRMap = _hRunnerMap)
{
int* pB = pBaseMap; // phMap is read only
int* pR = pRMap; // prHMap is read only
BitmapData bData = _buffer.LockBits(new Rectangle(0, 0, _buffer.Width,
_buffer.Height),
ImageLockMode.WriteOnly, _buffer.PixelFormat);
uint* pPixel = (uint*)bData.Scan0.ToPointer();
for ( int i = 0; i < _numPixelsInbuffer; i++ )
{
*pPixel = _palette[*pB+ZEROPOINT];
++pPixel;
if (*pR > *pB)
{
*pB += FADE;
regenerate = false;
}
else if (*pR < *pB)
{
*pB -= FADE;
regenerate = false;
}
pB++;
pR++;
}
_buffer.UnlockBits(bData);
}
_hDC.DrawImage(_buffer,0,0);
}
}
#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()
{
//
// Field
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(492, 371);
this.Name = "Field";
this.Text = "Field";
this.Closing += new
System.ComponentModel.CancelEventHandler(this.Field_Closing);
this.Load += new System.EventHandler(this.Field_Load);
}
#endregion
private void Field_Load(object sender, System.EventArgs e)
{
_hDC = this.CreateGraphics();
_buffer = new Bitmap(this.ClientSize.Width, this.ClientSize.Height, _hDC);
_numPixelsInbuffer = _buffer.Width*_buffer.Height;
_bufferWidth = _buffer.Width;
_bufferHeight = _buffer.Height;
_runner = new Thread(new ThreadStart(this.run));
_runner.Start();
}
private void Field_Closing(object sender,
System.ComponentModel.CancelEventArgs e)
{
_done = true;
// wait for thread to end naturally
while (_runner.IsAlive) {}
}
}
}