I made a 3d game and it is very simple now. It is like Minecraft. I use Mesh to print the graphics, but the fps only have 7-10! Does anyone know how to make the fps more higher at 3d games? Thank you.
Since you don't include any code to look at or any details on what you're doing other than Mesh to print graphics, all I can say is start removing things until it goes faster. How many meshes do you have, vertices, etc. What version iPad are you using. Give us as much info as you can.
@Gai_Gai Unfortunatly it runs at 0 FPS on my iPad Air. All I see is something blue and that's it. Any textures or whatever that you use, if they're not the built in Codea assets, they can't be seen by anyone else. They're local to you but blank for us. Maybe you can tell us what we're supposed to be seeing. I'm not going to spend any time trying to figure this out. Maybe someone else with a faster iPad will look into it, but it's too slow for me to do anything.
EDIT: Anytime you post code, put 3~'s on a line before and after the code so it formats correctly. I added them to your code above.
Well, I don't mean to be rude but I find your code a bit messy and hard to read, so I'll just give you tips (but I'm not an expert):
1. I recommend splitting your voxel world (aka blocky world) into chunks (like Minecraft) and each chunk will have a mesh. This way, you can draw only the chunks that are near the camera to reduce the amount of vertices being drawn.
2. I recommend culling (I think that's the right term!) the meshes. That means you need to get your code to figure out which sides of the blocks are covered. Only if a side is not covered by a block, should your code add vertices to the chunk's mesh for that side of the block.
3. Also, I see in your draw function, BlockMesh:setColors (255,255,255). It just needs to be called once (just after BlockMesh is declared).
@dave1707 I changed the texture, I think now you can see the texture.And thank for teach me how to use the "~~~". I think the problem that solw down the fps is the mesh, can you teach me how to use the mesh that it does not solw down the fps? Thank you.
@Kolosso , I already "culling" the mesh that between two blocks, It is better than the original one, but it only take fps higher a little (like 1-2). I try to put the DrawBlock:Draw as a comment but the fps is still low, and is a stop all the DrawBlocks class, the for is about 60. Does change the DrawBlock.vortex need a lot of time?
Is it culling every frame? If it is then I believe that's the problem. The vertices for the mesh only need to be set once unless the blocks will be changing. If that's the case, it should re-mesh only when there's a block change.
That's not really what I meant. If there is not that many blocks, you should use 1 mesh for all of them. If there are lots of blocks, you should split the blocks into chunks where each chunk has it's own mesh. You should make the vertices for your meshes once, at the setup function. Then draw the meshes in the draw function. Then change the vertices for the meshes when a block changes.
@Kolosso But the blocks I draw is 16*16 (a chunk), and the xyz of a block in a chunk is not the same, I need to change the xyz(vertices) every block, how can I make this faster?(easier?)
@Ignatz Is my way inefficient? I was telling @Gai_Gai that they should split the world into chunks, and make each chunk own a mesh that draws only the sides of the blocks that are visible. Then replace those meshes whenever a block changes (example: a block placed).
@Gai_Gai That is close to what I mean. You only need to make the vertices for your blocks once. Then you draw the meshes in the draw function. If there is a change, you remake the vertices of the meshes.
@Gai_Gai One thing that's slowing things down is the print statement in draw(). Comment that out. You never or almost never want to put a print statement in draw().
@Gai_Gai Deleting the print statement won't solve the whole problem, but it will help some. If you leave the print statement in there, it will eventually cause the program to slow down to a crawl and then crash.
@Kolosso I think I need 12 mesh for a type of block, because one mesh need to draw one triangle and the triangle has the same location and one block have 12 triangle so I think I need 12 mesh for a type of block.
@Gai_Gai If I look at your running code, there's a cube made up of 16x16x2 rectangles with the crate texture. On my iPad Air it runs at approx 7 FPS. Here's an example I put together with a cube made up of 17x17x2 rectangles with the crate texture. I changed the size of the texture to make it look solid. This runs at approx 50 FPS on my iPad. I'm not sure about everything you're doing in your code, but I just wanted to show you that the FPS can be increased. To see a 360 degree view of the inside of the cube, push cenX all the way to the right, then cenZ. Then push cenX all the way to the left, then cenZ. Repeat. Change eyeX,Y,Z for other views.
function setup()
parameter.watch("fps")
parameter.integer("eyeX",-4000,4000,0)
parameter.integer("eyeY",-200,200,40)
parameter.integer("eyeZ",-4000,4000,140)
parameter.integer("cenX",-1000,1000,-1000)
parameter.integer("cenZ",-1000,1000,-1000)
sides={}
for x=-8,8 do
for z=-8,8 do
table.insert(sides,side(x*20,40,z*20,"top"))
table.insert(sides,side(x*20,20,z*20,"bottom"))
end
end
for x=-8,8 do
for y=1,2 do
table.insert(sides,side(x*20,y*20,160,"front"))
table.insert(sides,side(x*20,y*20,-160,"back"))
table.insert(sides,side(180,y*20,x*20,"left"))
table.insert(sides,side(-180,y*20,x*20,"right"))
end
end
end
function draw()
background(40, 40, 50)
perspective(100)
camera(eyeX,eyeY,eyeZ, cenX,0,cenZ, 0,1,0)
for a,b in pairs(sides) do
b:draw()
end
fps=1/DeltaTime//1
end
side=class()
function side:init(x,y,z,pos)
v={ vec3(-10+x, -10+y, 10+z), -- Left bottom front
vec3( 10+x, -10+y, 10+z), -- Right bottom front
vec3( 10+x, 10+y, 10+z), -- Right top front
vec3(-10+x, 10+y, 10+z), -- Left top front
vec3(-10+x, -10+y, -10+z), -- Left bottom back
vec3( 10+x, -10+y, -10+z), -- Right bottom back
vec3( 10+x, 10+y, -10+z), -- Right top back
vec3(-10+x, 10+y, -10+z) } -- Left top back
self.ms=mesh()
self.ms.texture="Cargo Bot:Crate Green 1"
tex={ vec2(.1,.1),vec2(.9,.1),vec2(.1,.9),vec2(.9,.9) }
self.ms.texCoords={ tex[1],tex[2],tex[4],tex[1],tex[4],tex[3] }
if pos=="back" then
self.ms.vertices={ v[6],v[5],v[8],v[6],v[8],v[7] }
elseif pos=="front" then
self.ms.vertices={ v[1],v[2],v[3],v[1],v[3],v[4] }
elseif pos=="top" then
self.ms.vertices={ v[4],v[3],v[7],v[4],v[7],v[8] }
elseif pos=="bottom" then
self.ms.vertices={ v[5],v[6],v[2],v[5],v[2],v[1] }
elseif pos=="right" then
self.ms.vertices={ v[2],v[6],v[7],v[2],v[7],v[3] }
elseif pos=="left" then
self.ms.vertices={ v[5],v[1],v[4],v[5],v[4],v[8] }
end
self.ms:setColors(0,255,0,255)
end
function side:draw()
self.ms:draw()
end
@dave1707 can you teach me how does the code work? I'm not understand how the code work. How can the location of the mesh change without change the vertices?
@Gai_Gai The vertices values are different for each mesh. In the setup() function, I create an entry in the table sides for each mesh by calling side with different x,y,z values table insert(sides,side(x*20,40,z*20,"top")). The first for loop creates all the meshes for the top and bottom of the cube. The second for loop creates the sides. If you look at those, you'll see that there will be different values. I'm not sure if this is usable for what you might want to do, but then I don't know what you want to do. This was written just to show that the FPS can be increased. There are 714 meshes, each with different vertices. I believe that the number of meshes can be reduced to 6 by creating a mesh for each side with all the vertices for those sides.
If you are creating a set of blocks in a kind of wall that won't move, ie the wall won't break up into pieces, it's way more efficient to create the wall as a single 3D block, and tile the texture image on it to create the illusion of separate blocks.
As I said in my post above, the 714 meshes could be reduced to 6. Here's similar code to what I have above and it uses 6 meshes, one for each side, and runs at approx 60 FPS.
EDIT: Changed code.
function setup()
m=mesh()
for x=0,15 do
for y=0,15 do
m:addRect(x*42+21,y*42+21,42,42)
end
end
m.texture="Cargo Bot:Crate Blue 1"
img=image(42*16,42*16)
setContext(img)
m:draw()
setContext()
m=mesh()
for x=0,15 do
for y=0,1 do
m:addRect(x*42+21,y*42+21,42,42)
end
end
m.texture="Cargo Bot:Crate Green 2"
img1=image(42*16,42*2)
setContext(img1)
m:draw()
setContext()
parameter.watch("fps")
parameter.integer("eyeX",-4000,4000,0)
parameter.integer("eyeY",-200,200,0)
parameter.integer("eyeZ",-4000,4000,0)
parameter.integer("cenX",-1000,1000,-1000)
parameter.integer("cenZ",-1000,1000,-1000)
sides={}
table.insert(sides,side(100,21,100,"top"))
table.insert(sides,side(100,21,100,"bottom"))
table.insert(sides,side(100,21,100,"front"))
table.insert(sides,side(100,21,100,"back"))
table.insert(sides,side(100,21,100,"left"))
table.insert(sides,side(100,21,100,"right"))
end
function draw()
background(0)
perspective(100)
camera(eyeX,eyeY,eyeZ, cenX,0,cenZ, 0,1,0)
for a,b in pairs(sides) do
b:draw()
end
fps=1/DeltaTime//1
end
side=class()
function side:init(x,y,z,pos)
v={ vec3(-x, -y, z), -- Left bottom front
vec3( x, -y, z), -- Right bottom front
vec3( x, y, z), -- Right top front
vec3(-x, y, z), -- Left top front
vec3(-x, -y, -z), -- Left bottom back
vec3( x, -y, -z), -- Right bottom back
vec3( x, y, -z), -- Right top back
vec3(-x, y, -z) } -- Left top back
self.ms=mesh()
tex={ vec2(0,0),vec2(1,0),vec2(0,1),vec2(1,1) }
self.ms.texCoords={ tex[1],tex[2],tex[4],tex[1],tex[4],tex[3] }
if pos=="back" then
self.ms.texture=img1
self.ms.vertices={ v[6],v[5],v[8],v[6],v[8],v[7] }
elseif pos=="front" then
self.ms.texture=img1
self.ms.vertices={ v[1],v[2],v[3],v[1],v[3],v[4] }
elseif pos=="top" then
self.ms.texture=img
self.ms.vertices={ v[4],v[3],v[7],v[4],v[7],v[8] }
elseif pos=="bottom" then
self.ms.texture=img
self.ms.vertices={ v[5],v[6],v[2],v[5],v[2],v[1] }
elseif pos=="right" then
self.ms.texture=img1
self.ms.vertices={ v[2],v[6],v[7],v[2],v[7],v[3] }
elseif pos=="left" then
self.ms.texture=img1
self.ms.vertices={ v[5],v[1],v[4],v[5],v[4],v[8] }
end
self.ms:setColors(255,255,255,255)
end
function side:draw()
self.ms:draw()
end
Comments
Since you don't include any code to look at or any details on what you're doing other than
Mesh to print graphics
, all I can say isstart removing things until it goes faster
. How many meshes do you have, vertices, etc. What version iPad are you using. Give us as much info as you can.@dave1707 sorry, I forgot to put code...
There is all the code from my project.
@Gai_Gai Unfortunatly it runs at 0 FPS on my iPad Air. All I see is something blue and that's it. Any textures or whatever that you use, if they're not the built in Codea assets, they can't be seen by anyone else. They're local to you but blank for us. Maybe you can tell us what we're supposed to be seeing. I'm not going to spend any time trying to figure this out. Maybe someone else with a faster iPad will look into it, but it's too slow for me to do anything.
EDIT: Anytime you post code, put 3~'s on a line before and after the code so it formats correctly. I added them to your code above.
Well, I don't mean to be rude but I find your code a bit messy and hard to read, so I'll just give you tips (but I'm not an expert):
1. I recommend splitting your voxel world (aka blocky world) into chunks (like Minecraft) and each chunk will have a mesh. This way, you can draw only the chunks that are near the camera to reduce the amount of vertices being drawn.
2. I recommend culling (I think that's the right term!) the meshes. That means you need to get your code to figure out which sides of the blocks are covered. Only if a side is not covered by a block, should your code add vertices to the chunk's mesh for that side of the block.
3. Also, I see in your draw function,
BlockMesh:setColors (255,255,255)
. It just needs to be called once (just afterBlockMesh
is declared).@Kolosso Thank you for the help, very helpful.
@dave1707 I changed the texture, I think now you can see the texture.And thank for teach me how to use the "~~~". I think the problem that solw down the fps is the mesh, can you teach me how to use the mesh that it does not solw down the fps? Thank you.
@Kolosso , I already "culling" the mesh that between two blocks, It is better than the original one, but it only take fps higher a little (like 1-2). I try to put the DrawBlock:Draw as a comment but the fps is still low, and is a stop all the DrawBlocks class, the for is about 60. Does change the DrawBlock.vortex need a lot of time?
Is it culling every frame? If it is then I believe that's the problem. The vertices for the mesh only need to be set once unless the blocks will be changing. If that's the case, it should re-mesh only when there's a block change.
@Kolosso You mean one block use one mesh? I can try that. Because I use only one Mesh to draw all of the blocks and I change the vertices every block.
@Kolosso Thank you for the idea.
That's not really what I meant. If there is not that many blocks, you should use 1 mesh for all of them. If there are lots of blocks, you should split the blocks into chunks where each chunk has it's own mesh. You should make the vertices for your meshes once, at the setup function. Then draw the meshes in the draw function. Then change the vertices for the meshes when a block changes.
@Kolosso But the blocks I draw is 16*16 (a chunk), and the xyz of a block in a chunk is not the same, I need to change the xyz(vertices) every block, how can I make this faster?(easier?)
why are you changing vertices? Why not just translate the blocks?
@Ignatz so you mean mesh can translate? That is good idea, thank you for help me I will try it now.
@Ignatz Is my way inefficient? I was telling @Gai_Gai that they should split the world into chunks, and make each chunk own a mesh that draws only the sides of the blocks that are visible. Then replace those meshes whenever a block changes (example: a block placed).
@Kolosso so you mean that I only need to draw a block once if there is never will be a change?
@Gai_Gai That is close to what I mean. You only need to make the vertices for your blocks once. Then you draw the meshes in the draw function. If there is a change, you remake the vertices of the meshes.
@Kolosso But how can one mesh draw different xyz?
@Gai_Gai One thing that's slowing things down is the print statement in draw(). Comment that out. You never or almost never want to put a print statement in draw().
@Gai_Gai What do you mean?
@Kolosso How can the mesh know where to draw?
@Kolosso Because there is a lot of block at there and each block have a different location, how mesh know where to draw ?
@Gai_Gai Meshes can be translated with the
translate(x,y,z)
command. Is that what you were asking about?@dave1707 I delete the print, the fps is still low, I don't think this is the problem.
@Kolosso Yea! Thank you! I try this at begin of the draw blocks and all of the blocks all moved! That is work! Thank you very much to help me.
@Gai_Gai I'm happy to help!
@Kolosso By the way, do I need 12 mesh for one type of block? Because if I don't use it, the mesh need to change the vertices again.
@Gai_Gai Deleting the print statement won't solve the whole problem, but it will help some. If you leave the print statement in there, it will eventually cause the program to slow down to a crawl and then crash.
@dave1707 What if I change the print to text? I what to see the fps.
@Kolosso By the way, do I need 12 mesh for one type of block? Because if I don't use it, the mesh need to change the vertices again.
You can do a parameter.watch("FPS") and put FPS=1/DeltaTime//1 in the draw() function.
@dave1707 That is a great idea, thanks for the help.
By the way, do I need 12 mesh for one type of block? Because if I don't use it, the mesh need to change the vertices again.
@Gai_Gai What do you mean?
@Kolosso I think I need 12 mesh for a type of block, because one mesh need to draw one triangle and the triangle has the same location and one block have 12 triangle so I think I need 12 mesh for a type of block.
@Gai_Gai meshes can hold unlimited amount of triangles.
@Gai_Gai If I look at your running code, there's a cube made up of 16x16x2 rectangles with the crate texture. On my iPad Air it runs at approx 7 FPS. Here's an example I put together with a cube made up of 17x17x2 rectangles with the crate texture. I changed the size of the texture to make it look solid. This runs at approx 50 FPS on my iPad. I'm not sure about everything you're doing in your code, but I just wanted to show you that the FPS can be increased. To see a 360 degree view of the inside of the cube, push cenX all the way to the right, then cenZ. Then push cenX all the way to the left, then cenZ. Repeat. Change eyeX,Y,Z for other views.
@dave1707 thank you very much for the code
, I will study on it, thank you very much. 
@dave1707 can you teach me how does the code work? I'm not understand how the code work. How can the location of the mesh change without change the vertices?
@Gai_Gai The vertices values are different for each mesh. In the setup() function, I create an entry in the table sides for each mesh by calling side with different x,y,z values
table insert(sides,side(x*20,40,z*20,"top"))
. The first for loop creates all the meshes for the top and bottom of the cube. The second for loop creates the sides. If you look at those, you'll see that there will be different values. I'm not sure if this is usable for what you might want to do, but then I don't know what you want to do. This was written just to show that the FPS can be increased. There are 714 meshes, each with different vertices. I believe that the number of meshes can be reduced to 6 by creating a mesh for each side with all the vertices for those sides.If you are creating a set of blocks in a kind of wall that won't move, ie the wall won't break up into pieces, it's way more efficient to create the wall as a single 3D block, and tile the texture image on it to create the illusion of separate blocks.
As I said in my post above, the 714 meshes could be reduced to 6. Here's similar code to what I have above and it uses 6 meshes, one for each side, and runs at approx 60 FPS.
EDIT: Changed code.
You could make an if statement when the FPS is less than 40 then smooth graphics is disabled else smooth graphics is enabled.