How to make fps higher at a 3d game.

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. :slight_smile:

1 Like

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.

@dave1707 sorry, I forgot to put code…
There is all the code from my project.


--# Control
Control = class()

function Control:init(x)
    
end

function Control:draw()
    for k , touch in pairs (touches) do
        if touch.state == BEGAN then
            touchX,touchY = touch.x,touch.y
        elseif touch.state == MOVING then
            AngleY = AngleY - (touch.y - touchY) / 4
            AngleX = AngleX - (touch.x - touchX) / 4
            touchX,touchY = touch.x,touch.y
        end
    end
end

function Control:touched(touch)
    
end
--# DrawBlock
DrawBlock = class()

function DrawBlock:init(x)
    
end

function DrawBlock:draw()
    perspective ()
    for py = 1 , 256 do
        for px = 1 , 16 do
            for pz = 1 , 16 do
                if Blocks [py] [px] [pz] ~= 0 then
                    for i = 1 , 12 do
                        DrawBlocksList = {0}
                        if math.ceil (i / 2) == 1 then
                            if Blocks [py + 1] [px] [pz] == 0 then
                                DrawBlocksList [1] = 1
                            end
                        elseif math.ceil (i / 2) == 2 then
                            if Blocks [py] [px] [pz - 1] == 0 then
                                DrawBlocksList [1] = 2
                            end
                        elseif math.ceil (i / 2) == 3 then
                            if Blocks [py] [px] [pz + 1] == 0 then
                                DrawBlocksList [1] = 3
                            end
                        elseif math.ceil (i / 2) == 4 then
                            if Blocks [py - 1] [px] [pz] == 0 then
                                DrawBlocksList [1] = 4
                            end
                        elseif math.ceil (i / 2) == 5 then
                            if Blocks [py] [px - 1] [pz] == 0 then
                                DrawBlocksList [1] = 5
                            end
                        elseif math.ceil (i / 2) == 6 then
                            if Blocks [py] [px + 1] [pz] == 0 then
                                DrawBlocksList [1] = 6
                            end
                        end
                        if DrawBlocksList [1] ~= 0 then
                            for o = 0 , 1 do
                                BlockMesh.vertices = {vec3 (px * BlockWidth,py * BlockWidth,pz * BlockWidth) + Vertices [i] [1],vec3 (px * BlockWidth,py * BlockWidth,pz * BlockWidth) + Vertices [i] [2],vec3 (px * BlockWidth,py * BlockWidth,pz * BlockWidth) + Vertices [i] [3]}
                                BlockMesh.texCoords = TexCoords [i % 2 + 1]
                                if Blocks [py] [px] [pz] == 1 then
                                    if math.ceil (i / 2) == 1 then
                                        if BlockMesh.texture ~= "Cargo Bot:Crate Green 1" then
                                            BlockMesh.texture = "Cargo Bot:Crate Green 1"
                                        end
                                    elseif  math.ceil (i / 2) == 4 then
                                        if BlockMesh.texture ~= "Cargo Bot:Crate Green 1" then
                                            BlockMesh.texture = "Cargo Bot:Crate Green 1"
                                        end
                                    else
                                        if BlockMesh.texture ~= "Cargo Bot:Crate Green 1" then
                                            BlockMesh.texture = "Cargo Bot:Crate Green 1"
                                        end
                                    end
                                elseif Blocks [py] [px] [pz] == 2 then
                                    if BlockMesh.texture ~= "Project:FlatPlanet Dirt" then
                                        BlockMesh.texture = "Project:FlatPlanet Dirt"
                                    end
                                elseif Blocks [py] [px] [pz] == 3 then
                                    if BlockMesh.texture ~= "Project:FlatPlanet Stone" then
                                        BlockMesh.texture = "Project:FlatPlanet Stone"
                                    end
                                end
                                BlockMesh:draw ()
                            end
                        end
                    end
                end
            end
        end
    end
end

function DrawBlock:touched(touch)
    
end
--# SetUp
SetUp = class()

function SetUp:init(x)
    Vertices = {
    {vec3 (-1 * BlockWidth,0 * BlockWidth,-1 * BlockWidth),vec3 (0 * BlockWidth,0 * BlockWidth,-1 * BlockWidth),vec3 (-1 * BlockWidth,0 * BlockWidth,0 * BlockWidth)},
    {vec3 (0 * BlockWidth,0 * BlockWidth,-1 * BlockWidth),vec3 (0 * BlockWidth,0 * BlockWidth,0 * BlockWidth),vec3 (-1 * BlockWidth,0 * BlockWidth,0 * BlockWidth)},
    -- Top
    {vec3 (-1 * BlockWidth,-1 * BlockWidth,-1 * BlockWidth),vec3 (0 * BlockWidth,-1 * BlockWidth,-1 * BlockWidth),vec3 (-1 * BlockWidth,0 * BlockWidth,-1 * BlockWidth)},
    {vec3 (0 * BlockWidth,-1 * BlockWidth,-1 * BlockWidth),vec3 (0 * BlockWidth,0 * BlockWidth,-1 * BlockWidth),vec3 (-1 * BlockWidth,0 * BlockWidth,-1 * BlockWidth)},
    -- Front
    {vec3 (-1 * BlockWidth,-1 * BlockWidth,0 * BlockWidth),vec3 (0 * BlockWidth,-1 * BlockWidth,0 * BlockWidth),vec3 (-1 * BlockWidth,0 * BlockWidth,0 * BlockWidth)},
    {vec3 (0 * BlockWidth,-1 * BlockWidth,0 * BlockWidth),vec3 (0 * BlockWidth,0 * BlockWidth,0 * BlockWidth),vec3 (-1 * BlockWidth,0 * BlockWidth,0 * BlockWidth)},
    -- back
    {vec3 (-1 * BlockWidth,-1 * BlockWidth,-1 * BlockWidth),vec3 (0 * BlockWidth,-1 * BlockWidth,-1 * BlockWidth),vec3 (-1 * BlockWidth,-1 * BlockWidth,0 * BlockWidth)},
    {vec3 (0 * BlockWidth,-1 * BlockWidth,-1 * BlockWidth),vec3 (0 * BlockWidth,-1 * BlockWidth,0 * BlockWidth),vec3 (-1 * BlockWidth,-1 * BlockWidth,0 * BlockWidth)},
    -- Bottom
    {vec3 (-1 * BlockWidth,-1 * BlockWidth,-1 * BlockWidth),vec3 (-1 * BlockWidth,-1 * BlockWidth,0 * BlockWidth),vec3 (-1 * BlockWidth,0 * BlockWidth,-1 * BlockWidth)},
    {vec3 (-1 * BlockWidth,-1 * BlockWidth,0 * BlockWidth),vec3 (-1 * BlockWidth,0 * BlockWidth,0 * BlockWidth),vec3 (-1 * BlockWidth,0 * BlockWidth,-1 * BlockWidth)},
    -- Right
    {vec3 (0 * BlockWidth,-1 * BlockWidth,-1 * BlockWidth),vec3 (0 * BlockWidth,-1 * BlockWidth,0 * BlockWidth),vec3 (0 * BlockWidth,0 * BlockWidth,-1 * BlockWidth)},
    {vec3 (0 * BlockWidth,-1 * BlockWidth,0 * BlockWidth),vec3 (0 * BlockWidth,0 * BlockWidth,0 * BlockWidth),vec3 (0 * BlockWidth,0 * BlockWidth,-1 * BlockWidth)}
    -- Left
    }
    TexCoords = {
    {vec2 (1,0),vec2 (1,1),vec2 (0,1)},
    {vec2 (0,0),vec2 (1,0),vec2 (0,1)}
    }
end

function SetUp:draw()
    
end

function SetUp:touched(touch)
    
end

--# GeneratedTerrain
GeneratedTerrain = class()

function GeneratedTerrain:init()
    Blocks = {}
    for py = 0 , 257 do
        Blocks [py] = {}
        for px = 0 , 17 do
            Blocks [py] [px] = {}
            for pz = 0 , 17 do
                Blocks [py] [px] [pz] = 0
            end
        end
    end
    for px = 1 , 16 do
        for pz = 1 , 16 do
            Blocks [128] [px] [pz] = 1
            Blocks [127] [px] [pz] = 1
            for py = 1 , 3 do
                -- Blocks [128 - py] [px] [pz] = 2
            end
            for py = 1 , 124 do
                -- Blocks [125 - py] [px] [pz] = 3
            end
        end
    end
    Blocks [128] [1] [1] = 1
    Blocks [128] [2] [1] = 1
    Blocks [128] [1] [2] = 1
end

function GeneratedTerrain:draw()
    
end

function GeneratedTerrain:touched(touch)
    
end

--# Main
supportedOrientations (LANDSCAPE_ANY)
function setup()
    Variable:init ()
    BlockMesh = mesh ()
    -- BlockMesh:setColors (255,255,255,255)
end
sprite ()
function draw()
    background(176,233,252,255)
    lookX,lookY,lookZ = camX + math.sin (math.rad (AngleX)) * 10,camY + math.sin (math.rad (AngleY)) * 10,camZ + math.cos (math.rad (AngleX)) * 10
    camera (camX,camY,camZ,lookX,lookY,lookZ)
    DrawBlock:draw ()
    Control:draw ()
    print ("FPS : "..math.floor (1 / DeltaTime))
end

function touched (touch)
    if touch.state == ENDED then
        touches [touch.id] = nil
    else
        touches [touch.id] = touch
    end
end

--# Variable
Variable = class()

function Variable:init(x)
    BlockWidth = WIDTH / 8
    DrawBlocksList = {}
    -- block
    AngleX,AngleY = 180,180
    camX,camY,camZ = -300,130 * BlockWidth,BlockWidth
    lookX,lookY,lookZ = camX + math.sin (math.rad (AngleX)) * 10,camY + math.sin (math.rad (AngleY)) * 10,camZ + math.cos (math.rad (AngleX)) * 10
    -- camera
    touches = {}
    touchX,touchY = 0,0
    -- touch
    SetUp:init ()
    GeneratedTerrain:init ()
    -- init ()
    parameter.number ("camX",-1000,1000,-300)
    parameter.number ("camY",11000,20000,130 * BlockWidth)
    parameter.number ("camZ",-1000,1000,BlockWidth / 2)
    parameter.number ("AngleX",-1000,1000,-620)
    parameter.number ("AngleY",-1000,1000,-45)
end

function Variable:draw()
    
end

function Variable:touched(touch)
    
end

@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).

@Kolosso Thank you for the help, very helpful. :slight_smile:

@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. :slight_smile:

@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. :slight_smile:

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().