General discussion about LÖVE, Lua, game development, puns, and unicorns.
pgimeno
Party member
Posts: 1531
Joined: Sun Oct 18, 2015 2:58 pm

### Re: Why faking 3D nowadays?

4aiman wrote:
Wed Feb 28, 2018 4:32 pm

I guess I should've been more specific, though.
Love3d and other projects I saw here (love2d forums & github) use shaders and/or ffi in order to achieve proper 3d representation. Heck, even raycasters tend to be hardware-dependent (can't find a single raycaster that have textured floor/ceiling AND works on Android).

My interest lies not in love3d (or any other specific lib for that matter) and certainly not in raycasting.
I'm just wondering if there some newly-introduced built-in features of love2d 0.11.x to make perspective textured planes in 3d.

TL;DR
Something like love.graphics.rectangle(x,y,z,width,heigth, length,...) is a distant dream, but is it possible to go 3d without ffi and shaders as of now? Note that I'm talking about a cross-platform solution.
Without shaders, no. Shaders are at the core of Löve. They are always running, even if you don't define any.

To work in 3D with OpenGL, you need a vertex shader. I've looked more into love3d now, and it's now in my to-do list to try and make a raycasting-looking demo using actual GL 3D rendering. The key to obtain it is love.graphics.newMesh and an appropriate vertex and fragment ("pixel") shader, but especially vertex.

Now, take a look at this love3d demo: https://github.com/excessive/love3d-dem ... orward.lua

Pay special attention to how little it uses "l3d" and for what purpose. In that demo, it is used ONLY for two purposes: 1) to provide a depth buffer so that only the closest pixels are drawn, and 2) to not draw polygons that don't point to the camera. The rest is done with pure Löve. For something as simple as the raycasting-like demo I've mentioned earlier, you can do without both, and then you don't need love3d, just pure Löve 0.10. The love3d demo uses the IQM library, which in turn uses functions love.graphics.newMesh and Mesh:setVertexMap to create the mesh. IQM uses FFI to speed up loading of the file format it supports, but according to what I have seen so far, it seems to me that that loading could have been implemented in pure Lua with no problems. I am still studying it.

As I noted in a previous post, Löve 0.11 provides depth buffers, and that makes (1) unnecessary. It also introduces love.graphics.setMeshCullMode, which makes (2) unnecessary. This means that with 0.11, you don't need love3d to do real 3D like in that demo.

Edit: Simple proof of concept follows. I see no reason for it not to work in mobile. Note it does not use any libraries or FFI, but it uses a (trivial) vertex shader.

Code: Select all

local img, sb

extern mat4 view;

vec4 position(mat4 transform, vec4 vertex) {
// ignore love's transform which is only for 2d and use our own matrix
return view * vertex;
}
]]

img = love.graphics.newImage('image1.jpg')

-- A spritebatch is a mesh, so let's use that for simplicity
sb = love.graphics.newSpriteBatch(img, 64)
-- Generate 8x8 quads (image is 640x480 which means each quad is 80x60)
for y = 0, 7 do for x = 0, 7 do
quads[y * 8 + x + 1] = love.graphics.newQuad(x*80, y*60, 80, 60, 640, 480)
end end
for i = 1, 60 do
love.math.random(0, 7) * 80,
love.math.random(0, 7) * 60)
end

-- Compile the shader in place
end

local t = 0
function love.update(dt)
t = t + dt
end

function love.draw()
-- Use a preset matrix for demo purposes. A real matrix can be generated
-- with a 3D math library like CPML.
if love._version_major > 0 then
-- love 0.11 requires the matrix in row-major order
1.3, 0,    0, -450,
0, 0, -1.7, -120,
0, 1,    0,   50,
0, 1,    0,   50,
})
else
-- send the matrix in column-major order
1.3,    0,  0,  0,
0,    0,  1,  1,
0, -1.7,  0,  0,
-450, -120, 50, 50,
})
end

-- Toggle vertex shader on/off every second
if t >= 2 then
t = 0
elseif t >= 1 then
end

-- Draw the spritebatch
love.graphics.draw(sb)
end

Edit2: Oops, wrong image. The new one is 640x480.

Edit3: Updated to 11.0
Attachments
demo3d3.love
updated to 11.0
demo3d2.love
demo3d.love
Last edited by pgimeno on Wed Apr 04, 2018 4:08 pm, edited 2 times in total.
Thrust II Reloaded - GifLoad for Löve - GSpöt GUI - My NotABug.org repositories - portland (mobile orientation)
The MS-Github repositories I had have been closed after the acquisition announcement and will be removed in the near future.

pgimeno
Party member
Posts: 1531
Joined: Sun Oct 18, 2015 2:58 pm

### Re: Why faking 3D nowadays?

Here's something that is a bit more than the simple proof of concept above, but it's still little more than a mini-demo and not usable for anything serious yet, because it doesn't do any sorting: everything is rendered in the order it's created.

It allows you to draw 3D rectangles (actually rhomboids) given three 3D vertices: top left, top right, and bottom left (the bottom right one is calculated) and the UV corners. Everything is done via "the standard way" of using GPU rendering. By that I mean that it uses the same 3D projection method that actual 3D engines use. You don't have to worry about compatibility; the vertex shader is so very close to the Löve default that I'd say it's guaranteed to work on any platform where Löve works.

I've added on-screen buttons for testing in a mobile phone. I've tested in mine and it has no problems with it at all.

Edit: Updated to 11.0
Edit2: I had a typo in the matrix multiplication function, which somehow didn't have any visible effects, but I've fixed it anyway.
Attachments
rctest3.love
fix typo in matrix multiply
rctest2.love
updated to 11.0
rctest.love
Last edited by pgimeno on Thu May 17, 2018 2:00 pm, edited 2 times in total.
Thrust II Reloaded - GifLoad for Löve - GSpöt GUI - My NotABug.org repositories - portland (mobile orientation)
The MS-Github repositories I had have been closed after the acquisition announcement and will be removed in the near future.

Cruhan
Prole
Posts: 4
Joined: Sat Mar 18, 2017 3:45 pm

### Re: Why faking 3D nowadays?

interesting, it's a shame no raycaster engine gets really finished hehe.

PGUp
Citizen
Posts: 78
Joined: Fri Apr 21, 2017 9:17 am

### Re: Why faking 3D nowadays?

For fun, most of the time, also for game styles
-

Davidobot
Party member
Posts: 1145
Joined: Sat Mar 31, 2012 5:18 am
Location: Game-Dev. Land
Contact:

### Re: Why faking 3D nowadays?

pgimeno wrote:
Tue Mar 13, 2018 11:50 pm
...
pgimeno wrote:
Sun Mar 18, 2018 10:31 pm
...
Hey! Thanks so much for these examples - they make everything so much clearer. A quick question though - the example break in the recently-released 11.0 and I can't seem to figure out why. Would you be able to fix your wonderful example to work with the latest version of LOVE?
My library:
LovelyMoon

Check out my current project:
Raycaster

Oh hey, I have a website now!

pgimeno
Party member
Posts: 1531
Joined: Sun Oct 18, 2015 2:58 pm

### Re: Why faking 3D nowadays?

I think so. I'm sorta busy these days and it may take me some time. I also have Gspöt, GifLoad and T2R in my waiting queue, but this will probably be quick so I'll grab it first.
Thrust II Reloaded - GifLoad for Löve - GSpöt GUI - My NotABug.org repositories - portland (mobile orientation)
The MS-Github repositories I had have been closed after the acquisition announcement and will be removed in the near future.

pgimeno
Party member
Posts: 1531
Joined: Sun Oct 18, 2015 2:58 pm

### Re: Why faking 3D nowadays?

Turns out, Shader:send() sends the matrix in row-major order in 11.0 (thanks shakesoda for the info). I've updated the posts.
Thrust II Reloaded - GifLoad for Löve - GSpöt GUI - My NotABug.org repositories - portland (mobile orientation)
The MS-Github repositories I had have been closed after the acquisition announcement and will be removed in the near future.

Davidobot
Party member
Posts: 1145
Joined: Sat Mar 31, 2012 5:18 am
Location: Game-Dev. Land
Contact:

### Re: Why faking 3D nowadays?

pgimeno wrote:
Wed Apr 04, 2018 3:49 pm
...
Thanks a bunch! I tried changing the row/column major using the settings mentioned in the wiki, but it didn't work, as mentioned in the other post.

I've been trying to recreate your demos using CPML, but I can't quite the viewport matrix to match to yours. You create yours from scratch, while I use from_perspective. With values like (60, 4/3, 0.0625, 1024.0625) to mimick the ones in your example.

However, I've been unsuccessful.
My library:
LovelyMoon

Check out my current project:
Raycaster

Oh hey, I have a website now!

pgimeno
Party member
Posts: 1531
Joined: Sun Oct 18, 2015 2:58 pm

### Re: Why faking 3D nowadays?

Davidobot wrote:
Wed Apr 04, 2018 5:56 pm
I've been trying to recreate your demos using CPML, but I can't quite the viewport matrix to match to yours. You create yours from scratch, while I use from_perspective. With values like (60, 4/3, 0.0625, 1024.0625) to mimick the ones in your example.

However, I've been unsuccessful.
After from_perspective, you have to pre-multiply the matrix with a rotation of 90° over the Z axis (to make the view face east), and then another rotation of 90° over the X axis (to convert from top view to horizontal view).

I may have messed up the order. By pre-multiply I mean if the result of from_perspective is M and the rotation is R, you have to multiply R * M, not M * R.

Edit: Forgot to say, beware that CPML multiplication is backwards. https://github.com/excessive/cpml/issues/33

Edit 2: Yes I messed up the order. The perspective matrix is the last one to apply in the pre-multiply chain.
Last edited by pgimeno on Sat Apr 07, 2018 12:16 am, edited 1 time in total.
Thrust II Reloaded - GifLoad for Löve - GSpöt GUI - My NotABug.org repositories - portland (mobile orientation)
The MS-Github repositories I had have been closed after the acquisition announcement and will be removed in the near future.

Davidobot
Party member
Posts: 1145
Joined: Sat Mar 31, 2012 5:18 am
Location: Game-Dev. Land
Contact:

### Re: Why faking 3D nowadays?

pgimeno wrote:
Wed Apr 04, 2018 6:36 pm
...
Doing the premultiplication yields a matrix similar to the one that works, but it still doesn't. I'm not sure if I'm fundamentally misunderstanding something here.

The following code outputs this matrix:

Code: Select all

local axes = {
x = cpml.vec3.new(1, 0, 0),
y = cpml.vec3.new(0, 1, 0),
z = cpml.vec3.new(0, 0, 1),
}

camera = cpml.mat4.from_perspective(60, 4/3, 0.0625, 1024.0625)
premultz = cpml.mat4.from_angle_axis(math.pi/2, axes.z)
premultx = cpml.mat4.from_angle_axis(math.pi/2, axes.x)
cpml.mat4.mul(camera, camera, premultz)
cpml.mat4.mul(camera, camera, premultx)


Code: Select all

[ +0.000, +0.000, +1.299, +0.000, -1.732, +0.000, +0.000, +0.000, +0.000, +1.000, -0.000, -1.000, +0.000, +0.125, -0.000, +0.000 ]
While your matrix that works is:

Code: Select all

{
1.3,    0,  0,  0,
0,    0,  1,  1,
0, -1.7,  0,  0,
-450, -120, 50, 50,
}
Here is a .love file (11.0) that switches every second between the "camera" matrix (showing nothing) and your matrix.
Attachments
3DLOVE.love