Page 1 of 1

Floorcasting help - looks grainy

Posted: Sun Dec 30, 2018 12:03 pm
by Aidymouse
I've been at this for a long while and I'm completely at a loss.

I've been following Lode Vandavenne's excellent raycasting tutorial and am now trying to get floorcasting to work.
https://lodev.org/cgtutor/raycasting2.html

The only problem is, even after copying the code word for word (adjusting for lua syntax of course) multiple times, the end result always ends up with a terrible grainy look.

Image

On top of this, the floor texture seems to be displaying wrong regardless of the grainy effect. The texture appears to display straight down rather than how it should given the perspective.

My code for floorcasting looks as such:

Code: Select all

-- Floor drawing...
local h = self.screenH
local floorXWall, floorYWall

if side == 0 then
	if rayDirX > 0 then
		floorXWall = mapX
	elseif rayDirX < 0 then
		floorXWall = mapX + 1.0
	end
	
	floorYWall = mapY + wallX

elseif side == 1 then
	floorXWall = mapX + wallX
	
	if rayDirY > 0 then
		floorYWall = mapY
	elseif rayDirY < 0 then
		floorYWall = mapY + 1.0
	end

end

local distWall, distPlayer, currentDist

distWall = perpWallDist
distPlayer = 0

if drawEnd > 10000 then drawEnd = h end

for y = drawEnd+1, h do
	local currentDist = h / (2.0 * y - h)
	local weight = (currentDist - distPlayer) / (distWall - distPlayer)


	local currentFloorX = weight * floorXWall + (1.0 - weight) * self.posX;
	local currentFloorY = weight * floorYWall + (1.0 - weight) * self.posY;

	local floorTexX, floorTexY;
	local texWidth, texHeight = self.textures[1]:getWidth(), self.textures[1]:getWidth()
    floorTexX = round(currentFloorX * texWidth) % texWidth;
    floorTexY = round(currentFloorY * texHeight) % texHeight;

    self.textures[1]:drawPixel(floorTexX+1, floorTexY+1, math.floor(x), math.ceil(y))
end
Textures are their own file. The drawPixel method draws from an array generated inside the texture file. That array of pixels is generated here:

Code: Select all

tex.pixels = {}
for col = 1, tex.image:getWidth() do
	tex.pixels[col] = {}
	for row = 1, tex.image:getHeight() do
		table.insert(tex.pixels[col], love.graphics.newQuad(row, col, 1, 1, tex.image:getWidth(), tex.image:getHeight()))
		--tex.pixels[#tex.pixels+1] = )
	end
end
I'm super stuck and would love any help on the subject. Thank you in advance ^^ ^^

P.S. The code is extremely slow due to excessive use of quads, but I think I'll get around to fixing that when I actually get the code into a place where it works.

P.P.S. Sorry in advance for horribly ugly code. I think I've outlined the bits that are important and I've included a short text file explaining useful bits. Thanks again!

Re: Floorcasting help - looks grainy

Posted: Sun Dec 30, 2018 3:55 pm
by pgimeno
The .love file doesn't work, it lacks a map.txt file which is read via io.open, not love.filesystem.

Judging by the image, the effect you get looks like it's not applying the height of the floor correctly.

Re: Floorcasting help - looks grainy

Posted: Sun Dec 30, 2018 8:19 pm
by Aidymouse
Hi, thanks for the super fast reply!

Whoops, I forgot about my backwards file loading system. I think I've fixed it.
Also just realized I never attached the readme.

Thanks for your advice! I'm looking into how the height works now. I think you're right.

Re: Floorcasting help - looks grainy

Posted: Sun Dec 30, 2018 8:20 pm
by Aidymouse
OK this reply might make me look like an idiot. Can you just not attach text files directly or can I just not see them being attached?

EDIT: Okay there it is

Breakthrough! Also more problems.

Posted: Sun Dec 30, 2018 9:42 pm
by Aidymouse
Ah ha! I figured out by looking over the tutorial and comparing it to my own code that I screwed up the variable wallX.

Code: Select all

if side == 0 then
	wallX = self.posY + perpWallDist * rayDirY
else
	wallX = self.posX + perpWallDist * rayDirX
end

wallX = wallX - math.floor(wallX)
ballX = wallX

wallX = math.floor(wallX * texScaleWidth) -- texture width
wallX = wallX + 1
The last two lines there are what screwed me up, but I was able to put wallX into another variable, named ballX for now, and the floor comes out looking alright. At least better than what it was before.

Image
(Don't worry about the green line, that's a debug thing)

As you can see it looks all spiky and weird. I think this is due to lua rounding errors or perhaps part of a larger problem. It's hard to see in this image but you would think that one floor tile should be taken up by one, stretched, tile. However, this is not the case. It's easier to see with a different floor texture.

Image

The floor texture here is 100px by 100px, a perfect square, yet the floorcaster seems to fit 6 of them into one floor tile. This is strange, and leads to an effect while moving that makes it look like the walls are 'sliding' over the floor, seemingly because the walls move close faster than the floor texture scrolls.

One problem down and two more spring up. Ah, such is programming I suppose.

Any help would be greatly appreciated! ^^ ^^

EDIT: Attached the mostly working floorcaster.

Re: Breakthrough! Also more problems.

Posted: Mon Dec 31, 2018 12:09 am
by pgimeno
Aidymouse wrote: Sun Dec 30, 2018 9:42 pm As you can see it looks all spiky and weird. I think this is due to lua rounding errors or perhaps part of a larger problem.
That seems to be due to rounding problems indeed.
Aidymouse wrote: Sun Dec 30, 2018 9:42 pmIt's hard to see in this image but you would think that one floor tile should be taken up by one, stretched, tile. However, this is not the case. It's easier to see with a different floor texture.
The floor is correct in a sense; the problem is that the walls are floating over the floor. They are not drawn in all their height. The cause is the 2.5 factor found here:

Code: Select all

        lineHeight = self.screenH / perpWallDist / 2.5 -- Not local because I use it for floorcasting
Removing it makes everything look normal. If the walls are too high for your purposes, you need to adjust the currentDist by the same factor:

Code: Select all

            local currentDist = h / (2.0 * y-h) / 2.5
There seems to be also an offset whose cause I haven't traced.