Данная статья затрагивает особенности графического движка Blitz3D, в принципе эта статья написана исключительно для него, но, тем не менее, может содержать полезную информацию и для разработчиков на других графических движках.
Сейчас мы рассмотрим наиболее очевидный и часто применяемый способ поднятия fps, а также его применение. Я хочу затронуть тему, а точнее проблему, с которой сталкиваются многие начинающие разработчики. Многие из них, а возможно и вы задавались вопросом: «Я создаю уровень со ста деревьями и домами, но все жутко тормозит, а в других играх нет, помогите мне, как мне посадить на уровень сто миллионов деревьев без тормозов?». В этой статье я расскажу как.

Тормоза от количества объектов

Blitz3D обладает одной особенностью, он тормозит не столько от количества полигонов, как от количества обсчитываемых рендером объектов.

Для него огромная разница, что рендерить: 100 объектов по 1000 полигонов, или 1000 объектов по 100 полигонов.

Для этого я представляю вашему вниманию 2 теста:

Первый тест.
Скопируйте данный исходный код себе в редактор Blitz3D.

Запустите его. Запомните то количество fps, которое выдал вам тест.
Теперь найдите строчку Global Select_=0 и замените значение с 0 на 1. И запустите тест еще раз.

Обратите внимание на количество fps. Оно стало гораздо выше. Теперь давайте разберем исходный код, почему так происходит?

В первом случае у нас создаются кубики и просто парентяться к пивоту, который мы и вращаем. При этом каждый кубик является отдельным объектом и сохраняет свою независимость, мы можем его двигать или удалять.

Во втором случае мы создаем пустой меш. После позиционирования кубиков мы приаттачиваем наши кубики к данному мешу, а после удаляем их. Таким образом у нас остается один объект, который и облегчает работу рендера, тем самым повышая fps.
Недостаток такого способа очевиден. Объекты теряют независимость, зато fps повышается в несколько раз.

Graphics3D 800,600,32,2

SetBuffer BackBuffer()

SetFont LoadFont ("Arial Cyr",16)


cam=CreateCamera()

PositionEntity cam,0,0,-50

l=CreateLight()


Global frames_,render_time_,fps_


Global count=0


Global telo


Global Select_=0


;================================

; Pivot

;================================

If Select_=0 Then

telo=CreatePivot()


For x = - 15 To 15 Step 3

For y = - 15 To 15 Step 3

For z = - 15 To 15 Step 3

count=count+1

cube=CreateCube()

PositionEntity cube,x,y,z

EntityParent cube,telo


Next

Next

Next

EndIf


;================================

; Addmesh

;================================

If Select_=1 Then

telo=CreateMesh()


For x = - 15 To 15 Step 3

For y = - 15 To 15 Step 3

For z = - 15 To 15 Step 3

count=count+1

cube=CreateCube()

PositionMesh cube,x,y,z

AddMesh cube,telo

FreeEntity cube


Next

Next

Next

EndIf


Repeat

TurnEntity telo,1,1,1

UpdateWorld

RenderWorld

Text 10,10,"fps: "+FPS_Show()+" Objects: "+count+" Tris: "+TrisRendered()

Flip 0


Until KeyHit(1)

End


Function FPS_Show()

frames_=frames_+1

If MilliSecs()-render_time_=>1000 Then fps_=frames_ : frames_=0 : render_time_=MilliSecs()

Return fps_

End Function

Но всегда ли так происходит? А что если вы хотите сделать объекты интерактивными?
Рассмотрим второй пример исходного кода.
Вам знакома команда CameraRange? Правильно, она устанавливает радиус обзора камеры, все объекты, которые находятся за пределом радиуса, не поступают на рендеринг. Зачем я ее привел? Дело в том, что при объединении объектов в один меш, он всегда рендерится полностью, даже если большая его часть не видна. Это и станет нам полезным.

Скопируйте нижеследующий код:
Запустите его с параметром Global Select_=1 где все объекты объединяются в один меш. Объекты размещены таким образом, что напоминают нам лес или домики. У автора этой статьи тест показал максимальное значение fps=163. Прошу заметить, что в кадре рендерится постоянно 60018 полигонов, т.к. все объекты объединены в один меш.
Теперь изменим состояние переменной Select_ на 0. В данном режиме все объекты отдельны и рендерится каждый раз разное количество полигонов. Fps в данном случае 242. Улучшение есть, хоть и небольшое. Но огромный плюс данного метода это то, что все объекты интерактивны, вы можете к примеру сделать ломаемые деревья или разносимые в клочья дома. Так получается потому, что в камере рендерится меньшее количество полигонов. В своей игре вы должны настроить правильное расстояние в
CameraRange, которое вам угодно. Теперь вы сможете смело ставить на карту кучу интерактивных объектов.

Graphics3D 800,600,32,2
SetBuffer BackBuffer()
SetFont LoadFont ("Arial Cyr",16)
Global cam
cam=CreateCamera()
l=CreateLight()
;======================
; !
;======================
CameraRange cam,1,100
;======================
PositionEntity cam,0,3,0Global frames_,render_time_,fps_

Global telo

Global plane=CreatePlane()

Global count=0

Global Select_=0

;================================
; Pivot
;================================
If Select_=0 Then
telo=CreatePivot()

For x = - 450 To 450 Step 42
For z = - 450 To 450 Step 42
count=count+1
cube=CreateCylinder(32)
ScaleEntity cube,5,5,5
PositionEntity cube,x,0,z
EntityParent cube,telo

Next
Next
EndIf

;================================
; Addmesh
;================================
If Select_=1 Then
telo=CreateMesh()

For x = - 450 To 450 Step 42
For z = - 450 To 450 Step 42
count=count+1
cube=CreateCylinder(32)
ScaleMesh cube,5,5,5
PositionMesh cube,x,0,z
AddMesh cube,telo
FreeEntity cube

Next
Next
EndIf

Repeat

TurnEntity telo,0,.5,0
UpdateWorld
RenderWorld
Text 10,10,"fps: "+FPS_Show()+" Objects: "+count+" Tris: "+TrisRendered()
Flip 0

Until KeyHit(1)
End

Function FPS_Show()
frames_=frames_+1
If MilliSecs()-render_time_=>1000 Then fps_=frames_ : frames_=0 : render_time_=MilliSecs()
Return fps_
End Function

(Visited 381 times, 1 visits today)