Hi. It's been a while since I posted here, and my last posts are almost about this exact same subject. Just saying to demonstrate how annoying this is to me.
Here is the problem : I'm trying to make a decent raycaster in C#. The main issue is that for this to happen, I need pixel by pixel drawing. My previous raycaster used VS GDI+, and trough several tricks involving pointers and filling a bitmap byte by byte, I was able to obtain half decent results, and make an online server-client style 3d engine complete with a map builder and several really cool features. I unfortunately wasn't able to expand the project further due to poorly written code (I am an hobbyist, I study Business Administration at Uni) and the fact that my quick hack for performance was barely able to carry the bare minimum of what I needed to make a very bare bone raycaster possible. This came with very real sadness, the realization that the project I spent almost 2 years on was essentially useless, bloated and impossible to expand on.
Enough background. Now, starting anew, my main concern is to find a way to gain fast pixel by pixel control over the screen. I'm using SFML and C#. My current testbench is pretty simple, I'm using a method I found on the internet written for C++. I Adapted it for C#. I'm filling a Color[,] array (each color is a pixel) and then I copy the RGB values inside a byte[] array before moving them inside the texture buffer. I then display the texture on the screen. I'm not sure what the bottleneck is, the application is faster than my previous one, but it's still too slow for my liking. Raycasters work by redrawing stuff ontop of other stuff, and I fear that adding more stuff would creep it to an halt. I'm posting what I have as a testbench right now, any help would be greatly appreciated. Keep in mind I am not a professional programmer by any mean, I am pretty uncomfortable with pointers and true 3d stuff, but I will use them if I must.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SFML.Audio;
using SFML.Graphics;
using SFML.System;
using SFML.Window;
namespace RayCastFF
{
class Program
{
public static int TestCounter = 0;
public static Color[,] ScreenBuffer = new Color[640, 360]; //an array containing the color of all the pixel, this is intended to be the main target of all manipulation and draw call
public static Texture MainViewPort = new Texture(640, 360);//main screen texture
unsafe static void Main(string[] args)
{
//MAINWINDOW SETUP
RenderWindow window = new RenderWindow(new VideoMode(640, 360), "RayCaster");
while (window.IsOpen)//MAIN GAME LOOP
{
//CALL FOR UPDATE
Update();
//DRAW
window.Clear();
window.DispatchEvents();
Sprite mainviewport = new Sprite(MainViewPort);
window.Draw(mainviewport);//draw the texture over the screen
window.Display();
//TAKE INPUT
}
}
static void Update()
{
TestCounter++;
if (TestCounter > 639) { TestCounter = 0; }
//RESET THE BUFFER (COULD BE REMOVED LATER I GUESS)
for (int x = 0; x < 640; x++)
{
for (int y = 0; y < 360; y++)
{
ScreenBuffer[x, y] = Color.Black;
}
}
//DO STUFF
DrawLine(Color.Red, TestCounter, 200, 100); //(for this test, i simply draw a moving line)
//WRITING THE BUFFER INTO THE IMAGE
//THIS SHOULD ALWAYS BE THE LAST STEP OF THE UPDATE METHOD
byte[] pixels = new byte[640 * 360 * 4]; //640 x 360 pixels x 4 bytes per pixel
Color[] cpixels = new Color[640 * 360];//intermediary step to keep everything clear
for (int x = 0; x < 640; x++)
{
for (int y = 0; y < 360; y++)
{
cpixels[x+(640*y)] = ScreenBuffer[x, y];//make an intermediary array the correct dimention and arrange the pixels in the correct position to be drawn (separate step to keep everything clean, I find this operation incredibly confusing mainly because I had no idea how the pixels are supposed to be arrenged in the first place(still kind of dont))
}
}
for (int i = 0; i < 640 * 360 * 4; i += 4)//fill the byte array
{
pixels[i + 0] = cpixels[i / 4].R;
pixels[i + 1] = cpixels[i / 4].G;
pixels[i + 2] = cpixels[i / 4].B;
pixels[i + 3] = cpixels[i / 4].A;
}
MainViewPort.Update(pixels);//update the texture with the array
}
//[X , Y]
static void DrawLine(Color color, int Wpos, int Ytop, int Ybottom)//simple draw method making a vertical line
{
for (int y = Ybottom; y < Ytop; y++)
{
ScreenBuffer[Wpos, y] = color;
}
}
}
}
What I'd like to end up with is a very fast way to draw the pixels on the window by the abstraction of a single 2d array of 640x360 unit that I could easily and simply manipulate. However, while being simple, it's also somewhat slow. It's also using 30% GPU load for some reason on a 1070GTX 8GB. Again, any help would be greatly appreciated.
Thanks in advance.