Оптимизации
В тази тема ще покажа как можете да оптимизирате вашата 3D графика т.е. да не заемате излишно ценни ресурси като процесорно време и системна памет, които могат да бъдат използвани за нещо друго. Или да намалите общото качество на графиката за сметка на производителността и обратно. Като за начало ще започна с нещо по-лесно, а това е функцията glHint( ), благодарение на която можете да контролирате качеството на някои компоненти от вашата 3D графика. Ето нейния прототип :

glHint( GLenum target, GLenum mode ) - функцията приема само два аргумента. Втория аргумент определя режим и може да бъде един от трите аргумента :

GL_NICEST - за висококачествен режим GL_FASTEST - за високопроизводителен режим ( за сметка на качеството ) GL_DONT_CARE - режима не ни интересува. Какъвто се падне :)

А за първи аргумент може да подадете :

GL_FOG_HINT - определя качеството на замъгляванията. При високачествен режим мъглата се изчислява за всеки пиксел, a в противен случай - за всеки връх.

GL_POINT_SMOOTH_HINT, GL_LINE_SMOOTH_HINT, GL_POLYGON_SMOOTH_HINT - определя качеството на загладените ( antialiased ) точки, линии или полигони. При високачествен режим се използват по-голям брой полупрозрачни, пикселни единици за изглаждането на съответния обект.

GL_PERSPECTIVE_CORRECTION_HINT - определя точността на изчисленията, при интерполация на цветовите стойности и текстурните координати на обектите т.е. при умножението им с текущата перспектива на виждане.


Display List

А сега идва ред на една много ефективна оптимизация. Това са т.н. компилирани списъци ( Display List ) , в които могат да се съдържат най-различни OpenGL команди. Компилираните списъци се използват най-често при многократно изобразяване на едни и същи фрагменти от 3D графиката, например ако искате да изрисувате 20 пъти някаква фигура с определeни нормали и текстурни координати. Самата сила на компилираните списъци е че се съхранява крайния резултат от командите, а не самите команди. Това означава, че изчисленията ще бъдат направени само веднъж и след това резултата от тях ще бъде използван наготово. Веднъж създаден, компилирания списък не може да бъде променян. Обикновено компилираните списъци се създават преди да започне цикличното извикване на рендериращата функция.
За да създадете компилиран списък, трябва да използвате функциите :

void glNewList( GLuint list, GLenum mode );
void glEndList( void );

Целия код намиращ се между двете функции попада в списъка. Както виждате функцията glNewList( ) приема два аргумента. Първият представлява индентификационния номер ( някакво число ) на текущия списък, а вторият аргумент може да бъде :

GL_COMPILE - командите в списъка се компилират
GL_COMPILE_AND_EXECUTE - командите в списъка се компилират и след това се изпълняват

За да получите свободен индентификатор за списъка може да използвате функцията :

GLuint glGenLists( GLsizei range ) - тя приема броя на индентификаторите които искаме да резервираме и връща първия незает. Ако резервирате примерно 3 индетификационни номера и получите числото 5, това означава, че индентификатори на списък можете да използвате числата 5, 6 и 7.

След като вече сте създали вашия компилиран списък, най-вероятно ще искате да го извикате някаде във вашата рендерища функция т.е. компилираните команди от него да се изпълнят. Това става с функцията :

void glCallList( GLuint list ) - приема инд. номер на списък, който желаем да извикаме.

По всяко време може да унищожите определен списък/ци с функцията :

void glDeleteLists( GLuint list, GLsizei range ) - за първи аргумент трябва да подадете номера на първия компилиран списък, който искате да бъде унищожен, а за втори аргумент - броя на списъците, които да бъдат унищожени, като се започне от инд. номер на първия от тях. Т.е. ако подадете за първи и втори аргумент съответно 5 и 3, то списъците които ще бъдат унищожени ще са с нормера 5, 6 и 7.


Cull Face

Изрязването на дадена част от обект ( т.н. Cull Face ) , която не може да бъде видяна, а това най-често е задната страна, е още един добър начин за оптимизиране на 3D графиката. За да включите изрязването на дадена част от обект трябва да подадете на функцията glEnable( ) аргумента GL_CULL_FACE. Също така можете да определите коя част от обекта да не се вземе впредвид при негово изрисуване. Това става с функцията :

void glCullFace( GLenum mode ) - тя приема един от аргументите - GL_FRONT, GL_BACK или GL_FRONT_AND_BACK, като при избиране на последния от тях не се изрисува нищо друго освен линии и точки, ако сте използвали такива при изрисуването на обекта т.е. ако обекта е бил съставен от триъгълници, то той ще стане напълно невидим.


Последни съвети :

- опитвайте се да извиквате колкото се може по-малко функции от рода на glBegin( ), glEnd( ) и glBindTexture( ). Как? Ами просто трябва да подредите вашия кода така, че фигури от един и същи тип да се изрисуват наведнъж, с еднократно извикване на glBegin( ) и glEnd( ). По същия начин стои въпроса и с glBindTexture( ). Когато включите някоя текстура като текуща, е добре да изрисувате всички обекти които я използват, вместо да включвате друга, а след това да се връщате отново към предишната.

- добре е да използвате компилирани списъци винаги, когато е възможно да се възползвате от техните предимства.

- за изграждането на сложни триизмерни фигури използвайте триъгълници, понеже изрисуването на един триъгълник става много по-бързо отколкото на един четириъгълник, дори при изрисуването на множество четириъгълници е по-добре се използват по два триъгълника за всеки.

Има още много неща които могат да оптимизират вашата графика, но засега и тези са достатъчни. Някои от тях наистина са много полезни, особено компилираните списъци.

Автор: Иван Георгиев Иванов [ Nickname: tuschko ]
e-mail: tuschko@abv.bg


Този сайт е хостван от сървър на
Headoff Gaming Intranetwork