XNA Creators Club Online
Page 1 of 2 (28 items) 1 2 Next >
Sort Posts: Previous Next

I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

Last post 4/19/2009 4:57 AM by Bluebomber357. 27 replies.
  • 4/12/2009 5:02 PM

    I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Hey all, I recently found this article, http://student.kuleuven.be/~m0216922/CG/raycasting.html, and I was stunned at how easily a Wolfenstein 3D raycaster could be built. Naturally my first instinct was to put this thing on the 360 :D

    I did so quickly too, it wasn't too hard to port. I got the untextured version running like butter on my 360 and PC. It was no surprise, it only involved drawing 512 lines at a 512x384 resolution. The problem I have now is with my textured version. I can't just draw 512 lines, I have to draw every pixel (if there is a wall present there). So if I have a wall filling up my screen, all 512x384 points have to be drawn instead of just 512 lines. I wouldn't think that this would be a problem, its just points, but it does seem to run slower on my PC and my 360 says there is an error right when I start up the game on the 360:

    "An unhandled exception of type 'System.InvalidOperationException' occurred in Microsoft.Xna.Framework.dll

    Additional information: The amount of data being used to draw is too large for this drawing operation."

    Now is the part where I kindly ask for help, I would really like to run my textured raycaster on the 360. Are there any optimizations I could make to fix the problem? My code is at the bottom, its only 400 lines if you don't count the comments and using statements :) I believe you could just copy and paste this over a new xna project in visual studio in the Game1.cs class and see my raycaster for yourself :)

    BTW, I used this tutorial to figure out how to draw lines and points in XNA, http://msdn.microsoft.com/en-us/library/bb196414.aspx


    NOTE: I deleted the obsolete code from this post

  • 4/12/2009 6:57 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    ***UPDATE***

    I changed my code so that it draws a bunch of one pixel textures rather than points as above. Now I can run it on the 360, but its slow. I do not understand why drawing 320x240 one pixel textures would cause such a headache. Here is my updated code, please help me get this raycaster running faster :D

    NOTE: I deleted the obsolete code from this post


  • 4/12/2009 7:05 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Please don't post such large walls of code into the forums. Use something like paste.ziggyware.com and just link it.

    If it's of any interest to you or others, I did a little raycasting project about a year ago. I made it with the 3.0 CTP so it'll need to be upgraded, but it supported sprites and ran fine. I don't think I got to supporting textured ceilings or floors so those just wind up being solid colors. But otherwise I did try the code with 3.0 at one point and it runs on the 360. It's pretty nifty. :)
  • 4/12/2009 7:10 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Thanks for the tip on avoiding large code blocks.

    Do you remember how you drew your graphics, I still can't figure out why XNA can't render my 320x240 1 pixel textures faster :(
  • 4/12/2009 9:23 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    ***UPDATE***

    I found a big way to optimize my code. Now I can get a decent frame-rate on my 360, but only at 320x240 :(

    What I do now is take my screen size buffer of colors for each pixel, and copy it directly to a texture, and then just display the whole texture, rather than calling spriteBatch.Draw() 320x240 times for each 1 pixel texture. So calling spriteBatch.Draw once instead of 76,800 times.

    Now my performance on PCs is decent, but its still not smooth at full screen, and my performance on the 360 is rough at 320x240. Please help try and optimize this code :D

    Here is my current code: http://www.ziggyware.com/codepaste.php?pasteID=1247
  • 4/12/2009 10:14 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    At 1280x720 I get 32fps without moving the camera. Don't 'new' that spriteTexture every frame in draw, do it once and don't do it again, 38fps after I change that.
  • 4/12/2009 10:32 PM In reply to
    • (2330)
    • premium membership MVP
    • Posts 1,220

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    In general modern GPU's (like that found in your PC or the 360) are heavily optimized to do as much work as possible GPU-side with little intervention from the CPU.  Therefore a technique where you determine the final pixel color CPU-side and then just throw them all at the GPU is not ideal.  I don't know exactly how your technique works since you removed the code, so I'll just make some general suggestions for how to optimize for the 360:

    -Floating point math peformance sucks on the 360's CPU, for a few reasons.  Optimize out everything you can, and do as much calculation in GPU vertex/pixel shaders as possible.  If you're using the XNA math functions, make sure you use the by ref overloads in your tight inner loops.  You might even want to manually inline things like vector adds/multiplies, since the .NET CF sucks at inlining.  Before you took down your code I saw you were using double's everywhere...I'm honestly not sure whether those will even run at full 64-bit precision on the XBox 360 but if it does, I'm sure it will be slower than using float's. Probably worth swapping those out to see if you get any improvement.

    -Minimize your Graphics API calls, they will cause a lot of CPU overhead.  This means things like setting members of GraphicsDevice.RenderState, doing stuff with Effect's, and especially DrawPrimitives/DrawIndexedPrimitives.  Lots of Draw calls will tank your performance really quickly.  A modern GPU works best when the CPU hands it a large batch of work that it can chew through with little intervention. 

    Matt Pettineo | DirectX/XNA MVP


    Ride into The Danger Zone | PIX With XNA Tutorial
  • 4/12/2009 10:34 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    ajmiles, I tried moving the new "spriteTexture = new Texture2D" to my initialize function, but it causes a runtime error: "The size of the data passed in is too large or too small for this resource."

    What did you do when you moved it out of the draw function?

    BTW, how can you see the Frames-Per-Second?


    MJP, my code isn't gone, I just moved it to Ziggyware, I left a link to it :)
  • 4/12/2009 10:46 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    You need to move it to LoadContent where you originally had the loading of the pixel texture (that's no longer needed). I literally just cut and paste the line:

    spriteTexture = new Texture2D(graphics.GraphicsDevice, screenWidth, screenHeight, 0, TextureUsage.None, SurfaceFormat.Color);

    from Draw() into LoadContent().

    As for FPS, I just used Fraps, but you can write a pretty simple frame counter a bit like this (may not compile):

    // Member variables
    int frames = 0;
    float millis = 0;

    //In Draw()
    millis += (float)gameTime.ElapsedGameTime.TotalMilliseconds;
    frames++;

    if(millis > 1000) { Console.WriteLine(frames); frames = 0; milllis = 0; }

  • 4/12/2009 10:50 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    When I put that line of code in LoadContent I get this error:

    InvalidOperationException
    The operation was aborted. You may not modify a resource that has been set on a device, or after it has been used within a tiling bracket.


    BTW, MJP, I got rid of all my doubles and turned them into floats, I did not get a noticeable bump, but I am sure it helps. I need to tackle some of your other suggestions. Keep the suggestions coming :D

    Here is my most up to date code: http://www.ziggyware.com/codepaste.php?pasteID=1248
  • 4/12/2009 10:57 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    You need : "GraphicsDevice.Textures[0] = null;" before you SetData(foregroundColors) in Draw to unset the texture from the device.
  • 4/12/2009 11:08 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Okay, I got that working now. That one change seems to give a boost in areas with lots of pixels drawn on the 360 :)

    Now its running pretty good on the 360 at 320x240, but there is still slowdown when I am close a wall in front of me. When I try to increase the resolution to 720x480, it starts to get real choppy, but wayyyyy better than before... :(

    Let me know if you guys see any other problems with my code :)

    Here is my most up to date code: http://www.ziggyware.com/codepaste.php?pasteID=1249
  • 4/13/2009 3:36 AM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Bluebomber357:
    Do you remember how you drew your graphics, I still can't figure out why XNA can't render my 320x240 1 pixel textures faster :(
    I didn't render one pixel at a time; that's just silly :). What I did was use SpriteBatch.Draw once per vertical slice. It's pretty easy to set up the source and destination rectangles to get the section of the texture I want and render a vertical slice. This means that at the ideal I'm only rendering 320 sprites to draw all the walls.
  • 4/13/2009 4:54 AM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    As of now, I just figure out the color of each pixel and put them a Texture2D. I then call spriteBatch.Draw() once, is my current implementation silly? It is a ton faster than my last one, but it still bogs down on the 360 if my resolution is greater than 320x240 and the screen is full of wall pixels...
  • 4/13/2009 5:04 AM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Check out the link to the project I worked on. If you render one sprite per vertical slice, you can render at 720p with only drawing 1280 sprites, as opposed to drawing a sprite per pixel. When I converted my project to 360, I was able to run at full 720p with no frame rate issues. So definitely work on optimizing the drawing. Doing each pixel independently is not going to be efficient at all.
  • 4/13/2009 7:33 AM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Nick Gravelyn:
    Please don't post such large walls of code into the forums. Use something like paste.ziggyware.com and just link it.

    If it's of any interest to you or others, I did a little raycasting project about a year ago. I made it with the 3.0 CTP so it'll need to be upgraded, but it supported sprites and ran fine. I don't think I got to supporting textured ceilings or floors so those just wind up being solid colors. But otherwise I did try the code with 3.0 at one point and it runs on the 360. It's pretty nifty. :)


    How exactly would I implement floors/ceilings in your code? I tried implementing the floor today, but failed.
  • 4/13/2009 7:59 AM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    thefalling:
    Nick Gravelyn:
    Please don't post such large walls of code into the forums. Use something like paste.ziggyware.com and just link it.

    If it's of any interest to you or others, I did a little raycasting project about a year ago. I made it with the 3.0 CTP so it'll need to be upgraded, but it supported sprites and ran fine. I don't think I got to supporting textured ceilings or floors so those just wind up being solid colors. But otherwise I did try the code with 3.0 at one point and it runs on the 360. It's pretty nifty. :)


    How exactly would I implement floors/ceilings in your code? I tried implementing the floor today, but failed.
    I have no idea. :p That's why I never implemented it. Figured I would just go the Wolfenstein route of not actually having floors and ceilings, but instead just rendering a fullscreen sprite that was split in the center and had a color or gradient on top for the ceiling and a color or gradient on bottom for the floor. Since all ways are centered on the screen, as long as you don't support an area without walls, this illusion holds perfectly and even adds to that "old school" feel of pre-Doom raycasting.
  • 4/13/2009 9:55 AM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Long ago in the mists of time I had to do a similar raycaster.

    When I did the floor/ceiling I just did another pass through the ray caster but casting rays in the YZ plane instead of the XZ plane.

    Okay I needed two maps etc, but it did allow variable ceiling heights.

    Information is not knowledge, knowledge is not wisdom, wisdom is not truth, truth is not beauty, beauty is not love, love is not music, music is the best! Wisdom is the domain of the Wis (which is extinct).
  • 4/13/2009 3:41 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Nick I still do not understand. I am not rendering a 1 pixel texture for every wall pixel anymore. Instead I am only making on texture, that contains all the wall pixels and then just doing one draw call. Shouldn't mine be efficient enough? I feel like having 1280 1 pixel wide textures and calling the draw method 1280 times would be slower (obviously I am wrong somewhere though).
  • 4/13/2009 3:47 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Setting the data of a texture is likely to be slower than just drawing 1280 sprites. 1280 sprites is nothing; especially to the 360. But sending over the whole texture takes a good chunk of bandwidth, not to mention if you are using any GetData calls on textures which are even more slow than SetData. Plus you still wind up looping over every pixel of the screen potentially, if the user is staring right into a wall.

    If you look at my code, it has the logic for taking a wall texture and finding the vertical slice that aligns with the particular wall slice I'm trying to draw. It uses that information to compute a Draw call with a source and destination rectangle so that it renders perfectly. Using this method there are no GetData calls and no SetData calls and will be much faster than trying to make a wall texture and draw it all in one go. The other benefit is that as you start to add things like sprites into your system, if your walls all draw as one single sprite, you will not be able to do proper Z testing on your sprites. Or rather, you may be able to, but it's going to be more work than if you were drawing each vertical slice of the walls individually.
  • 4/13/2009 8:29 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    I changed my code around so that it could render 1280 sprites, one for each slice. It works but it is much slower than before. I did not get rid of my spriteTexture.setData call though. I can get rid of it by having pre-made textures waiting to be loaded, rather than storing my texture in an array of RGB color and then using .setData on my texture. Is setData that big a deal? I'll change my code a little later when I have some more free time, let me know if there is any other red flags in my code.
  • 4/13/2009 9:49 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    At this point I have to ask, why?

    Apart from as an exercise to learn how 3D rendering works from first principles, or for rendering 3D on a low powered machine such as Zune, what is the point of ignoring all that awesome 3D hardware in your Xbox?

    Even if you want an old-skool Wolf3D visual style, you could get that far more easily and efficiently by rendering your scene as triangles in the normal way.
    XNA Framework Developer - blog - homepage
  • 4/13/2009 10:01 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    The answer for why would be just because raycasting is an interesting technique. It is even more interesting that the 360, and to a lesser extent, my two PCs can't just flat out run my program at 60fps at full resolution. Also, I stumbled on this C++ tutorial and it was very simple, and it didn't use triangles...

    I feel like I am really close to the end (I hope), I believe I have my code like the raycasterX code, let me know if there are any glaring issues. I believe I am rendering the same way now, but I am still not getting a good framerate at 720x480 on my 360... :(

    BTW, now I have no .setData or .getData calls, I draw only one sprite per vertical line of resolution, and to run this code you'll need a texture named, "testTexture" in your content folder. My performance is very different now, the framerate seems to be much more consistent, and doesn't drop sharply when close to a wall, but the framerate hovers around 35fps on my pc at 720p, unlike before where it'd get to 60 if I wasn't close to a wall.

    Link to code: http://www.ziggyware.com/codepaste.php?pasteID=1259


  • 4/13/2009 10:01 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    Bluebomber357:
    Is setData that big a deal?
    Yes, it is. Manually editing those textures is going to kill (or at least hurt) perf. It works on hardware with direct frame buffer access, but to set a texture on the GPU will stall things. If you look at my code, you'll see a technique for rendering without ever having to call SetData on a texture.
  • 4/13/2009 10:21 PM In reply to

    Re: I ported an awesome raycaster from C++ to XNA, but it won't run on my 360 anymore, please help :)

    FTW! Ah, I forgot to delete that "for loop" for the vertical pixels in my new code. After I did that I can finally run this thing +30fps on my PC at 720p, and smoothly at 720x480 on my 360. The game still runs slow at 720p on my 360, a consistent 10-20is frame per second though. I'll post my latest code below. If anyone sees anything bad (I'll keep poking at it too), let me know :D

    Thanks Nick for all the help so far, my program is running faster and with less code :)

    Link to code: http://www.ziggyware.com/codepaste.php?pasteID=1261
Page 1 of 2 (28 items) 1 2 Next > Previous Next