Fellow up with my last post, i'm currently trying to implement 2s sprites in my raycaster written in C# following Lodev tutorial. Unfortunately, i'm out of luck. I'm using native csharp class to keep it simple and the set pixel class is so slow it's unusable. I tried an alternative way drawing sprites and masking out part that should be obstructed by walls without any good results. Either it's completely unusable or way to slow. I want to be able to draw few dozens of sprites at the same time. Can anyone please help me ?
The struggle with raycasting in C# intensifies, need help
From your previous post, it looks like you're using a WinForms project. If that's still true, and you're using standard WinForms drawing, use Bitmap.LockBits to update the entire bitmap at once instead of using multiple SetPixel calls (see link).
http://msdn.microsoft.com/en-us/library/5ey6h79d(v=vs.110).aspx
NOTE: You don't have to do both a read and a write. You can raytrace to an array and then copy your array into the bitmap without copying the bitmap into your array first.
Alright so far so good. Found this page explaining how to use LockBits pretty well http://bobpowell.net/lockingbits.aspx . Got the code to work and fill my bitmap with blue pixel but i am unfamiliar with pointers and bytes. How would i write a simple function analogous to the SetPixel method ? I am looking at something like this :
(Let's say you started with a default WinForms example - use the following code in the Form1.cs file. Also make sure to enable "Allow unsafe code" in the Project properties' Build section)
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;
namespace BitmapSetExample
{
public partial class Form1 : Form
{
Bitmap bmp;
public Form1()
{
InitializeComponent();
bmp = new Bitmap(256, 256, PixelFormat.Format32bppArgb);
uint[,] pixels = new uint[256,256];
for (uint y=0; y<256; ++y)
for (uint x=0; x<256; ++x)
pixels[x,y] = 0xFF000000 + (x ^ y);
pixels[0,0] = 0xFFFF0000; // Use a red pixel to indicate where the 0,0 coordinate is (currently this example has 0,0 at the upper left)
SetBitmap32bppArgb(bmp, pixels);
}
public static unsafe void SetBitmap32bppArgb(Bitmap bmp, uint[,] pixels)
{
int width = Math.Min(bmp.Width, pixels.GetLength(0));
int height = Math.Min(bmp.Height, pixels.GetLength(1));
var bitmapData = bmp.LockBits(new Rectangle(0,0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
for (int y=0; y < height; ++y)
{
uint *row = (uint*)(bitmapData.Scan0.ToInt64() + y * bitmapData.Stride);
for (int x=0; x<width; ++x)
row[x] = pixels[x,y];
}
bmp.UnlockBits(bitmapData);
}
protected override void OnPaint(PaintEventArgs e)
{
e.Graphics.DrawImageUnscaled(bmp, 0, 0);
}
}
}
Where pixels is a 2D array of uints, where each uint represents one pixel and has the hexadecimal layout: 0xAARRGGBB.
uint alpha = valueBetween0and255;
uint red = valueBetween0and255;
uint green = valueBetween0and255;
uint blue = valueBetween0and255;
uint pixelValue = (alpha << 24) | (red << 16) | (green << 8) | blue;
Thank you alot for your help. While your solution looks appealing, i find it way easier for me to use function analogous to the native ones. Problem solved and thanks again you made my day, project was on hold last week because of this issue.
You can do insanely fast 2d sprite drawing with OpenTK/OpenGL, and get cheap zooming, rotations, and cross-platform as well.