trying to make my own "Separate Logic and render fps" - help :)

Started by Santiago, September 12, 2019, 18:15:30

Previous topic - Next topic

Santiago

Hi, i trying to do my own version to separate the frames logic from renders

but i can find the way or condition to make it.

the main fail condition are in the update_fps function.
line 208.

you can change the number of objetcts to simulate low render.

sometimes my brain not work, so i start to change simbols, > = < + 1 - 1 in my conditions :)

i stock here....  Sorry my english again :)



AppTitle "Separar la logica de los renders. "


Global gancho = 1000
Global galto = 800
Global gbits = 0
Global gmode = 2



;the idea is to have 60 logic frames per second
;and render only each X logic frame if i have my 60 logic frames per second
;I don't won render more than 60 times per second, becouse if i don't change the logic, the render will be the same

;! Sorry my english and spansh use

Graphics3D gancho,galto,gbits,gmode




Global cam = CreateCamera()
MoveEntity cam,0,20,-80
TurnEntity cam,20,0,0
Global light = CreateLight(1)
MoveEntity light,-50,-50,-50


Global fps_logica = 60 ;cantidad de veces que se debe repertir la logica por segundo / how many logic frame i wan per second
Global fps_render = 60  ;cantidad de veces que quisieramos que se renderee. / how many render frame i wan per second

Global fps_start = 0 ;cuando se inicio el loop / loop millisec start

Global fps_frame ;el numero de frames que llevamos en este segundo / count frames
Global fps_last ;millisec en el que se inicio el ultimo fps / last millisec frame

Global fps = 0 ;cantidad de veces que se repitio el loop principal / frame per second main loop
Global fps_logicos = 0 ;cantidad de veces que se repitio la logica en 1 segundo / logic frames per second count
Global fps_renders = 0 ;cantidad de veces que se rendereo en un segundo / render frames per second count

Global fps_do_render    ;indica si hay que renderear / i must render?
Global fps_do_logic     ;indica si hay que procesar logica / i must do the logic?

Global fps_frame_render ;cantidad de veces que se rendereo en el ultimo segundo / count how many renders in last second
Global fps_frame_logica ;cantidad de veces que se calculo la logica en el ultimo segundo / count how many logic have in the las second

Global fps_last_millisec_logic ;ultimo milisegundo en el que se calculo la logica / when was the last logic millisecs
Global fps_last_millisec_render ;ultimo milisegundo en el que se calculo el RENDER / when was the last render millisect

Global fps_last_render_delay = 0 ; / count how many millisecs take to render
Global fps_last_logic_delay = 0 ; / count how many millisecs take to do the logic

Global fps_step_render_per_frame ;cantidad de frames que tienen que esperar para renderear / how many steps  logic to do the render
Global fps_frame_steped ;veces que llevo haciendo la logica sin renderear / how many times i make logic witouth render



Type objecto   ;objets to render something

Field entidad

End Type


; higher more slow :)
Global cube_count = 10000

For i = 1 To cube_count

a=100
b=30

o.Objecto = New objecto
o\entidad = CreateCube()
PositionEntity o\entidad,Rnd(-a,a),Rnd(-b,b),Rnd(-a,a)
RotateEntity o\entidad,Rnd(360),Rnd(360),Rnd(360)
Next



While Not KeyHit(1)

update_fps()

If fps_do_logic = 1 Then logica()

If fps_do_render = 1 Then render()


If KeyHit(57) Then

For o.objecto = Each objecto
FreeEntity o\entidad
Delete o
Next


cube_count = Rnd(100,10000)
For i = 1 To cube_count

a=100
b=30

o.Objecto = New objecto
o\entidad = CreateCube()
PositionEntity o\entidad,Rnd(-a,a),Rnd(-b,b),Rnd(-a,a)
RotateEntity o\entidad,Rnd(360),Rnd(360),Rnd(360)
Next

End If



Wend

End

Function logica()

Local time = MilliSecs()

fps_frame_logica = fps_frame_logica + 1
fps_last_millisec_logic = MilliSecs()
fps_do_logic = 0
fps_frame_steped = fps_frame_steped + 1



;game logic

For o.Objecto = Each objecto
TurnEntity o\entidad ,1,Sin(MilliSecs()*.1),1
EntityAlpha o\entidad,1
EntityColor o\entidad,128 + Sin(o\entidad + MilliSecs()*.1)*100,128 + Cos(o\entidad + MilliSecs()*.1)*100,128 + Tan((MilliSecs())*.1)*100
Next


CameraClsColor cam, 58 + Sin(MilliSecs()*.01)*10,28 + Cos(MilliSecs()*.1)*10,0


;count how much millisecs i use to do this function
fps_last_logic_delay = MilliSecs() - time



End Function

Function render()

Local time = MilliSecs()

fps_frame_render = fps_frame_render + 1
fps_last_millisec_render = MilliSecs()
fps_do_render = 0
fps_frame_steped = 0

RenderWorld

Color 10,10,10
Rect 0,0,500,120,1

Color 0,255,0
Text 10,10,"Loop fps : " + fps
Color 255,255,0
Text 10,25, "Logic fps : " + fps_logicos
;Text 200,25, " > " + fps_last_logic_delay + " ms"
Color 255,100,0
Text 10,40, "Render fps : " + fps_renders
;Text 200,40, " > " + fps_last_render_delay + " ms"

Color 255,255,255
Text 10,55,"fps_step_render_per_frame " + fps_step_render_per_frame
Text 10,70,"press SPACE to change the count of cubes " + cube_count

Flip 0

fps_last_render_delay = MilliSecs() - time


End Function

Function update_fps()

Local render_step_time
Local logic_step_time

Local render_millisec_step_recomended  = 1000/60 ;veces maxima que se deberia renderear por segundo.



If fps_start = 0 Then
fps_start = MilliSecs()
End If

If MilliSecs() > fps_start + 1000 Then

fps_renders = fps_frame_render
fps_frame_render = 0

fps_logicos = fps_frame_logica
fps_frame_logica = 0


fps_start = MilliSecs()
fps = fps_frame
fps_frame = 0

End If

fps_frame = fps_frame + 1


; debo calcular logica en este frame?
; Do logic?
logic_step_time = 1000 / fps_logica

If fps_last_millisec_logic + logic_step_time  <  MilliSecs() Then
fps_do_logic = 1
Else
fps_do_logic = 0
End If



; Debo calcular render?
; Render??
fps_step_render_per_frame  = 5


;here i have the problem!!! in this conditions!
fps_step_render_per_frame =  1+Int(Float((fps_last_render_delay * 60)/1000))*2
If fps_step_render_per_frame < 1 Then fps_step_render_per_frame = 1
If fps_logicos < fps_logica Then fps_step_render_per_frame = fps_step_render_per_frame

;this work but dont know how to do it
;fps_step_render_per_frame = 3
If fps_logicos < fps_logica Then fps_step_render_per_frame = fps_step_render_per_frame + fps_logica-fps_logicos-1

If  fps_frame_steped => fps_step_render_per_frame  And fps_logicos <= fps_logica Then
fps_do_render = 1
Else
fps_do_render = 0
End If


End Function








Santiago

now i refresh the code, maibe i found the solution, but i wait for your opinion.

saludos!

RemiD

i was more talking about making your code / game / program like the driver of separate systems / entities, which can be updated / rendered separately.
so that you don't need to update all systems / entities each mainloop.

a good example is the GUI, you don't need to update / redraw it each frame, since it depends if the user has interacted with it or not. (personaly i store the GUI in a big image, and each GUI area in a smaller image, same for HUD)
and also you can subdivide a GUI in areas, and only update the necessary ones, same thing for HUD, for animations, for particles emitters and particles, for shadows, for glow, for AI sensing / thinking / pathfinding etc...

also a smart approach is to update one or a few entities each mainloop (until it exceed xms) instead of all entities

going further with the previous approach is to update a system / entity during several mainloops instead of one.
for example you can subdivide a procedure in steps, and store the step number in a field of the system / entity, and continue the procedure each mainloop for one step instead of all steps.

and for rendering, it make sense to render the far away elements not often ( as "impostors" (=textured quads) / "skyboxes" (textured flipped cube/cylinder) ) , and the near elements, which are in the camera field of view, visible (hence hidden surface determination/culling), less often...

Santiago

Thanks RemiD, it really opens my mind to read all that again and again.

I do not know at what time you choose to always go a rough path of programming.

The things you mention are very appropriate and intelligent ways that for some reason never apply.

I will be trying to apply and fully understand all of this.

thank you!

RemiD

if i find it, i will post an example on how to use millisec values to choose which entity to update next.
i have used this for real time lighting shading using my custom vertices lighting shading procedure, but updating the appearances of only one turning moving animating shape per mainloop / frame. (so the procedure runs one time per mainloop / frame for one entity, instead of 10-15 times for all entities !)
i consider the entities which are in the camera field of view, and visible, and then using the stored millisec values, determine which one was updated the longest time ago... and update this one in priority...
here : https://www.syntaxbomb.com/index.php/topic,6227.0.html

maybe it can give you some ideas...

Santiago

:) thanks.

Now i start a new project, to apply all this  new concepts.

i separete the units, from propertys, movements, physics, like independ types, and only use what is need for units.

and for movement, i go to use Last_update_millisecs, to apply movement, far units, maibe i can move it each 1 second, or 10 seconds steps, if i know when was the last time i update that unit,  i don't need to move each frame.


i separet the units from entitys, now the entitys only for the units in the view-range.



I have to break the idea that I have in my head, that the code has to be as realistic as life. and make the game as false as a television studio, that if there is a unit 100km away, don't worry about how your physics will respond, because simply NO ONE SEES IT!

I will process all this little by little, with a new project to apply all these new concepts!

RemiD

Quote
that the code has to be as realistic as life. and make the game as false as a television studio, that if there is a unit 100km away, don't worry about how your physics will respond, because simply NO ONE SEES IT!
that's the idea, yes 8)

Santiago

Hi, I'm trying to understand the following.

When making an image_gui, which I only update every x milliseconds, I find the following problem ..

I use FASTIMAGE, but I can't capture the image buffer to put it inside the gui_image image.





function update_gui_image()

SetBuffer ImageBuffer(gui_image)
Cls
Color 0,0,0
Rect 0,0,gancho,galto,1

Color 0,255,0
Text 10,10,"Loop fps : " + fps
Color 0,155,0
Text 10,25, "Logic fps : " + fps_logicos
Text 200,25, " > time : " + fps_last_logic_delay + " ms"

Color 155,100,0
Text 10,40, "Render fps : " + fps_renders
Text 200,40, " > time : " + fps_last_render_delay + " ms"

Color 55,100,155
Text 10,55,"Gui_update/s " + fps_gui_update_per_sec + " / " + fps_gui_pudates_this_sec



Color 255,255,255
Text 10,100,"Millisecs : " + MilliSecs()
SetBuffer BackBuffer()




if i use

stardraw()
setcolor 255,255,0
drawtext "texto",10,10
drawrect 100,100,100,100
enddraw

i can't capture the last draw made with fastimage


when using Fast_image, where do the iamgenes go ?, how can I capture them in the buffer of an image


sorry my ugly english!

RemiD

i don't know what happens when using fastext, but with Blitz3d, when your use renderworld (to render the 3D scene), the render is an image.

Santiago

Quote from: RemiD on October 01, 2019, 20:24:33
i don't know what happens when using fastext, but with Blitz3d, when your use renderworld (to render the 3D scene), the render is an image.

ohhh!!

Learn to pronounce
I didn't know that! Knowing that now I may think of how to solve it.

the truth is that it always cost me to understand the issue of frontbuffer and backbuffer.

I use it, but without understanding it :)

i am a beast

thanks RemiD!

RemiD

maybe do some tests with copyrect() to capture (a part of) a buffer (like imagebuffer, texturebuffer, backbuffer, frontbuffer) and transfer it to another buffer, all are images in a way...

Santiago

Thanks RemiD.

i read than draw fastlibs need Renderworld, and Blitz3d only can renderworld in Backbuffer(), so, i capture Backbuffer with copyrect and works perfect!!!


Thanks Again!