## Simple LOVE Raytracer Code (both untextured and textured)

Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

### Re: Simple LOVE Raytracer Code (both untextured and textured

IndieKid wrote:How do you create a floor based on another matrix table (like map {{1,1,1...0,1}})?
That information is provided in this link: http://lodev.org/cgtutor/raycasting2.html

Be mindful of the fact that Love is not at all optimized for doing individual pixel-based rendering, so you're very likely to get poor performance at high resolutions.
IndieKid
Citizen
Posts: 80
Joined: Sat Dec 22, 2012 7:05 pm
Contact:

### Re: Simple LOVE Raytracer Code (both untextured and textured

Inny wrote:
IndieKid wrote:How do you create a floor based on another matrix table (like map {{1,1,1...0,1}})?
That information is provided in this link: http://lodev.org/cgtutor/raycasting2.html

Be mindful of the fact that Love is not at all optimized for doing individual pixel-based rendering, so you're very likely to get poor performance at high resolutions.
Thanks a lot, that seems to be a very good tutorial for what I was looking for! I'm going to spend some time on it.
Last edited by IndieKid on Mon Dec 24, 2012 7:05 pm, edited 1 time in total.
IndieKid
Citizen
Posts: 80
Joined: Sat Dec 22, 2012 7:05 pm
Contact:

### Re: Simple LOVE Raytracer Code (both untextured and textured

Simple question about syntax in Lua: how should I write this in Lua?

Code: Select all

--floor
buffer[x][y] = (texture[3][texWidth * floorTexY + floorTexX] >> 1) & 8355711
--ceiling (symmetrical!)
buffer[x][h - y] = texture[6][texWidth * floorTexY + floorTexX]
This draws floor and ceiling.
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

### Re: Simple LOVE Raytracer Code (both untextured and textured

See https://love2d.org/wiki/love.graphics.point
So, probably like this:

Code: Select all

love.graphics.setColor( however you store your textures )
love.graphics.point(x+0.5, y+0.5)

Again, doing this 76800 times per frame is slow slow slow, and you'll have some sucky framerat.e
Roland_Yonaba
Inner party member
Posts: 1563
Joined: Tue Jun 21, 2011 6:08 pm
Contact:

### Re: Simple LOVE Raytracer Code (both untextured and textured

IndieKid wrote:Simple question about syntax in Lua: how should I write this in Lua?

Code: Select all

--floor
buffer[x][y] = (texture[3][texWidth * floorTexY + floorTexX] >> 1) & 8355711
--ceiling (symmetrical!)
buffer[x][h - y] = texture[6][texWidth * floorTexY + floorTexX]
This draws floor and ceiling.

Oh, bitwise operations.
Well, there are no standard support for bitwise operations in Lua 5.1 (that is the version on Lua that comes along with Löve).
So you can grab a C bitwise operations library (they are numerous) and call them with require. Or, you can grab a pure Lua implementation.
See D. Manura's BitNumberLua
IndieKid
Citizen
Posts: 80
Joined: Sat Dec 22, 2012 7:05 pm
Contact:

### Re: Simple LOVE Raytracer Code (both untextured and textured

Inny wrote:Again, doing this 76800 times per frame is slow slow slow, and you'll have some sucky framerat.e
Then any other ideas on how to add textures to floor and ceiling?
IndieKid
Citizen
Posts: 80
Joined: Sat Dec 22, 2012 7:05 pm
Contact:

### Re: Simple LOVE Raytracer Code (both untextured and textured

Roland_Yonaba wrote:Oh, bitwise operations.
Well, there are no standard support for bitwise operations in Lua 5.1 (that is the version on Lua that comes along with Löve).
So you can grab a C bitwise operations library (they are numerous) and call them with require. Or, you can grab a pure Lua implementation.
See D. Manura's BitNumberLua
Thanks for this information, but I don't really understand how to add textures to floor and ceiling, and because of that I don't need bitwise op. yet. Thanks anyway
scutheotaku
Party member
Posts: 235
Joined: Sat Dec 15, 2012 6:54 am

### Re: Simple LOVE Raytracer Code (both untextured and textured

IndieKid wrote:
Inny wrote:Again, doing this 76800 times per frame is slow slow slow, and you'll have some sucky framerat.e
Then any other ideas on how to add textures to floor and ceiling?
I believe that the easiest way to do floors (aside: whenever I'm referring to floors, I'm usually also referring to ceilings since the idea would be almost the same) would be to just draw them as textured quads. The problem with that is a big one, at least as far as LOVE is concerned. As of yet, there just isn't a good way to transform quads like we'd need to. Ideally, we should be able to set the coordinates of each vertex of each quad, though this currently isn't possible. If it was...you'd need a way to figure out where you are on the floor (so that the texture doesn't move as you move), which would probably be the hardest part. The second hardest part would be figuring out what "angle" to draw the floor at...but that wouldn't be too hard. See here: http://www.permadi.com/tutorial/raycast/rayc11.html & here http://www.permadi.com/tutorial/raycast/rayc12.html for an idea behind the math.

Using quads like this, if it were possible, you wouldn't be drawing things the pixel-by-pixel approach (which is slow in LOVE, or just about any framework/engine where you can't access the screen buffer). Though this approach could also result in some culling or overdraw issues, if you didn't account for it. For the culling issues, you'd just need to make sure that the floor is drawn before everything else, that way sprites and walls will cover it up (though this get slightly more complicated if you want multiple levels, I think). Ideally though, your engine would attempt to avoid these culling issues by only drawing the floor where needed. For the overdraw issues...well, there's no easy way to avoid that here, but I think that the gain from this approach (compared to pixel-by-pixel drawing) would far exceed the loss from overdraw in this case.

Now, if you want different floor levels, this makes things more complicated. In that case, your best bet would be to take the sector approach. Each sector would essentially be a convex polygon, and it would have its own floor and ceiling height. This is the approach that the DOOM and Build (Duke Nukem 3D) engines took (though they're overall approach to rendering and visibility was MUCH different). Alternatively, you could make it so that every tile could have a different floor and ceiling height...but then you'd either need 1. a floor and ceiling quad for each tile (which could cost a lot), or 2. more complicated math that would be able to merge the floor and/or ceiling quads of adjacent tiles with the same floor and/or ceiling height. If you think about it, this tile approach (which is also, basically, the approach taken by the Ultima Underworld/System Shock 1 engine, is basically the same as the sector approach, except that the tiles have a fixed size and shape, whereas the sector method allows each sector to be any size or shape).

If you'd rather render the floors the same as the walls (or if you don't feel like waiting for better transformation in LOVE), then I would suggest rendering them with horizontal lines instead of the vertical lines that the walls use. This is how the Build engine does it too. You should be able to re-appropriate some of Lode's code for this method, as I used and modified his textured wall code (compare my code to his if you want to see what I mean).

[EDIT: Also, for another method, see this post and the one right after it: viewtopic.php?f=4&t=6834&start=50#p47786 ]

Now for some more general information...

Once you get into the realm of "raycasting" floors and ceilings on modern software (particularly with something like LOVE), your best bet, in my humble opinion, is to start looking at engines like DOOM and Build or even the Ultima Underworld engine, and NOT at engines like Wolfenstein 3D or the ones in tutorials like Lode's and Permadi's (or in any of those hundreds of awful QBASIC tutorials). The older ways of doing it just don't translate well to things like LOVE.

Since most of us probably aren't interested in implementing a BSP tree like DOOM had (though personally I'm a fan of this type of system), I think it'd be worth looking a Build related things. Here are some links that may prove useful if you are wanting to go in that direction (many of them are cached versions of threads from JonOF's now-offline forum. Any posts be someone named "Awesoken" are from Ken Silverman, the designer of the Build engine):
http://forum.zdoom.org/viewtopic.php?f=4&t=5109
http://dukertcm.com/knowledge-base/sour ... d-ken.html

Don't forget that you can download the source code to the Build engine!
Here's JonOF's Windows and Linux ports: http://www.jonof.id.au/jfbuild
There's also a whole bunch of info on the engine, as well as C and QBASIC source code to several early prototypes (including an early grid-based version of the Build engine, which may prove useful), on this page of his website: http://advsys.net/ken/build.htm

If you have any questions about the Build engine, it can't hurt to contact Ken directly through his website. I can't guarantee he'll respond, but he seems like a pretty nice, helpful guy.

If you're interested in the DOOM engine, here are some things that may be useful:
http://en.wikipedia.org/wiki/Doom_engine (<<<contains a very good description of how the engine handles floors and ceilings)
http://doomwiki.org/wiki/Doom_engine
http://doomwiki.org/wiki/Doom_rendering_engine
http://en.wikipedia.org/wiki/Binary_space_partitioning
http://fabiensanglard.net/doomIphone/do ... nderer.php
http://fabiensanglard.net/doomIphone/index.php

You can also check out the Doom source code (but, as Fabien Sanglard puts it, it has "very little to no comments, won't compile, miss [sic] sound subsystem source code (due to a licensing problem)":
http://www.doomworld.com/idgames/index.php?id=14576
ftp://ftp.idsoftware.com/idstuff/doom/linux/

You'd probably be better off looking at the code of one of the source ports. Chocolate Doom can be a good option, particularly if you're familiar with SDL (since it ports everything to SDL):
http://www.chocolate-doom.org/wiki/inde ... olate_Doom
Though, of course, there are other source ports (many of which add features and change things) like BOOM, ZDoom, Vavoom, EDGE, Doomsday, etc...
http://doomwiki.org/wiki/Comparison_of_ ... urce_ports
http://doomwiki.org/wiki/Source_port#Sources

Also, taking a look at the source code to the official iPhone version of Wolfenstein 3D may be of some interest to you (particularly on how this updated version of the engine uses quads to draw the wall [iOS doesn't let apps talk to the frame buffer]), if you're experienced enough with C, Objective-C, and OpenGL to understand it:
http://fabiensanglard.net/wolf3d/index.php
ftp://www.idsoftware.com/idstuff/wolf3d ... .0_src.zip

The iPhone version of DOOM does things similarly:
http://fabiensanglard.net/doomIphone/index.php
https://github.com/id-Software/DOOM-iOS

---

As for me...I STILL can't figure out what I'm do wrong with the table sorting...!

---

EDIT:
I'm not experienced enough with LOVE or Lua or anything to really say this definitely...BUT theoretically it seems like you could write the pixel-by-pixel method in C/C++ (and maybe even use Lode's code almost exactly) and then, either by way of adding it to LOVE or maybe by way of a .dll, somehow reference that in LOVE? I don't know...

EDIT AGAIN:
There's some really interesting info on the Ultima Underworld/System Shock 1 rendering engine on this page:

Remember that Ultima Underworld, while slightly slow compared to the Wolf3D, DOOM, and Build engines, had textured walls, floors, and ceilings, as well as variable height and sloped floors and ceilings, yet it came out before Wolf3D.

EDIT ONCE MORE:
Here's an interesting quote from Doug Church, one of the programmers who worked on Ultima Underworld, describing Ultima Underworld's render engine:
" However, let me second what Dan Schmidt said in the guestbook back in August about the description of the UW engine you guys have up on the page. Namely, UW _was not_ a raycasting engine. While UW did use a tilemap to store the world, that has nothing to do with the rendering model. In general, I'd suggest that the "world rep" and "rendering engine" be considered separate things when discussing game technology, because they very often are. In UW, we had a tile based world. The renderer used the tiles to explore the view cone and do a high level cull operation. From the list of visible tiles, we generated full 3d polygons, in the traditional XYZ sense, and handed them off to a rendering back end and rendered each poly in 3d as is. That is also how the 3d models like the ankh shrines or benches were done, which clearly aren't "raycast" model 3d objects. Now, in practice, many of our 3d primitives did things like normal checks first, and then chose which algorithim to rasterize with based on scale/normal/etc of the surface being rendered."
Source: http://www.peroxide.dk/underworld.shtml

Combine that knowledge with the explanation of UUW's tile system from the TSSHP link I gave, and that paint a picture of what I feel would be the best (as far as an optimal features:speed ratio) 2.5D engine currently possible with LOVE. At least, it seems like LOVE's speedy drawing of textured quads makes this method the most attractive. Assuming, of course, that we can actually transform quads in this way...I'll say, it seems extremely strange that this isn't a feature yet (though I realize that LOVE is still a WIP, so I'm not upset or anything). I hope that it is something that's added soon!
Last edited by scutheotaku on Wed Dec 26, 2012 6:30 am, edited 1 time in total.
Jasoco
Inner party member
Posts: 3655
Joined: Mon Jun 22, 2009 9:35 am
Location: Pennsylvania, USA
Contact:

### Re: Simple LOVE Raytracer Code (both untextured and textured

IndieKid wrote:
Inny wrote:Again, doing this 76800 times per frame is slow slow slow, and you'll have some sucky framerat.e
Then any other ideas on how to add textures to floor and ceiling?
Well, skimming over that huge block of text above because it's a lot of text, I did it by using Canvases.

Which would probably bum a lot of people out if you used. Also, it's not exactly the same graphically, but it works well enough no one would really care. But it used canvases.

But yes, it could all be completely solved if Löve could transform textured quads the way we require. A lot more 3D projects would probably crop up as a result even though Löve isn't meant for 3D. But dangit, we're ambitious little scoundrels.
scutheotaku
Party member
Posts: 235
Joined: Sat Dec 15, 2012 6:54 am

### Re: Simple LOVE Raytracer Code (both untextured and textured

Jasoco wrote:
IndieKid wrote:
Inny wrote:Again, doing this 76800 times per frame is slow slow slow, and you'll have some sucky framerat.e
Then any other ideas on how to add textures to floor and ceiling?
Well, skimming over that huge block of text above because it's a lot of text, I did it by using Canvases.

Which would probably bum a lot of people out if you used. Also, it's not exactly the same graphically, but it works well enough no one would really care. But it used canvases.
This method creates a fairly substantial FPS hit too, right? I notice that the FPS listed in your screenshot is a lot lower than what I was getting from your most recently released WolfenLove demos at a high resolution. Also, does changing the image scaling filter reduce the jaggedness along the edges of each "floor block" that you see in your screenshot?

### Who is online

Users browsing this forum: No registered users and 9 guests