![]() |
|
![]() |
![]() |
Новости | Конференция | Чат | База данных | Творчество | Сообщество | О сайте | English |
![]() |
Помощь сайту |
![]() |
![]() |
![]() |
![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Глава 7. VBO Что же это? Это технология с помощью которой можно поместить информацию о вершинах напрямую в видеокарту и оставить её там. Дает огромный прирост скорости работы приложения. Чтобы внедрить её в наш движок, вначале нужно загрузить расширение GL_ARB_vertex_buffer_object, поддерживаемое всеми современными видеокартами. http://www.gamedev.ru/terms/VBO еще тут есть подробная информация. Итак, как вы рисуете объекты. Есть 3 способа. 1) самый медленный glBegin(GL_TRIANGLES); for i:=0 to count-1 do begin glTexCoord2fv(@ Texcoord[i]); glNormal3fv(@ Normal[i]); glVertex3fv(@ Vertex[i]); end; glEnd; 2)более быстрый Идея такова не давать карточке вершини «поштучно», а отправить сразу массивами разрешаем массивы glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); в элементе массива 2 значения (если у вас 3, то пишите 3) GL_FLOAT тип данных (С++ float, Delphi single) 0 у вас есть отдельно каждый массив, данные идут подрят @ Texcoord[0]-указатель на первый элемент массива glTexCoordPointer(2, GL_FLOAT, 0, @ Texcoord[0]); у нормалей всегда 3 элемента, поэтому нас даже не спрашивают glNormalPointer(GL_FLOAT, 0, @ Normal[0]); glVertexPointer(3, GL_FLOAT, 0, @ Vertex[0]); рисование GL_TRIANGLES то же что и в glBegin (GL_TRIANGLES -самый эффективный) Есть еще один массив Indx массив индексов, служит для экономии памяти. Например вам нужно вывести вершины 1,2,3, потом 2, 3, 4. Без массива Indx вам нужно будет объявить 2,3 дважды. А с помощью Indx пишите в нем так [1,2,3,2,3,4] и все. Count кол-во элементов в Indx GL_UNSIGNED_INT тип элементов в Indx (в Delphi cardinal) @ Indx[0] указатель на первый элемент массива glDrawElements(GL_TRIANGLES, Count, GL_UNSIGNED_INT, @ Indx[0]); ВНИМАНИЕ! Даже если у вас в Indx все идет без повторений, это все равно быстрее, чем без массива Indx запрещаем массивы glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); Теперь вернемся к VBO. Идея такова, вместо того чтоб брать данные об массивах с оперативки, нужно брать их из видяхи. Делается так: glBindBufferARB( GL_ARRAY_BUFFER_ARB, VBOpoints[1] ); glNormalPointer( GL_FLOAT, 0, nil ); glBindBufferARB( GL_ARRAY_BUFFER_ARB, VBOpoints[2] ); glTexCoordPointer( 2, GL_FLOAT, 0,nil ); glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, VBOpoints[3] ); glBindBufferARB( GL_ARRAY_BUFFER_ARB, VBOpoints[0] ); glVertexPointer( 3, GL_FLOAT, 0, nil ); glDrawElements(GL_TRIANGLES, Count, GL_UNSIGNED_INT, nil); glVertexPointer последняя команда перед glDrawElements!! так быстрее Видим, появился массив VBOpoints. генерируем 4 имени под 4 массива glGenBuffersARB( 4, @ VBOpoints[0] ); данные из Vertex (Count*12 --размер) glBindBufferARB( GL_ARRAY_BUFFER_ARB, VBOpoints[0] ); glBufferDataARB( GL_ARRAY_BUFFER_ARB, Count*12, Vertex, GL_STATIC_DRAW_ARB ); данные из texcoord (Count*12 --размер) glBindBufferARB( GL_ARRAY_BUFFER_ARB, VBOpoints[1] ); glBufferDataARB( GL_ARRAY_BUFFER_ARB, Count*12, Normal, GL_STATIC_DRAW_ARB ); данные из texcoord (Count*8 --размер) glBindBufferARB( GL_ARRAY_BUFFER_ARB, VBOpoints[2] ); glBufferDataARB( GL_ARRAY_BUFFER_ARB, Count*8, texcoord, GL_STATIC_DRAW_ARB ); данные из Indx (Count*4 --размер) glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, VBOpoints[3] ); glBufferDataARB( GL_ELEMENT_ARRAY_BUFFER_ARB, Count*4, Indx, GL_STATIC_DRAW_ARB ); чистим оперативку SetLength(vertex,0); SetLength(normal,0); SetLength(texcoord,0); SetLength(indx,0); После завершения работы нужно почистить данные о VBO glDeleteBuffersARB(4,@ VBOpoints[0]); Чтобы использовать VBO нужно загрузить поддержку расширения GL_ARB_vertex_buffer_object: function Load_GL_ARB_vertex_buffer_object: Boolean; var extstring: String; begin Result := FALSE; extstring := String(PChar(glGetString(GL_EXTENSIONS))); if glext_ExtensionSupported('GL_ARB_vertex_buffer_object', extstring) then begin glBindBufferARB := wglGetProcAddress('glBindBufferARB'); if not Assigned(glBindBufferARB) then Exit; glDeleteBuffersARB := wglGetProcAddress('glDeleteBuffersARB'); if not Assigned(glDeleteBuffersARB) then Exit; glGenBuffersARB := wglGetProcAddress('glGenBuffersARB'); if not Assigned(glGenBuffersARB) then Exit; glIsBufferARB := wglGetProcAddress('glIsBufferARB'); if not Assigned(glIsBufferARB) then Exit; glBufferDataARB := wglGetProcAddress('glBufferDataARB'); if not Assigned(glBufferDataARB) then Exit; glBufferSubDataARB := wglGetProcAddress('glBufferSubDataARB'); if not Assigned(glBufferSubDataARB) then Exit; glGetBufferSubDataARB := wglGetProcAddress('glGetBufferSubDataARB'); if not Assigned(glGetBufferSubDataARB) then Exit; glMapBufferARB := wglGetProcAddress('glMapBufferARB'); if not Assigned(glMapBufferARB) then Exit; glUnmapBufferARB := wglGetProcAddress('glUnmapBufferARB'); if not Assigned(glUnmapBufferARB) then Exit; glGetBufferParameterivARB := wglGetProcAddress('glGetBufferParameterivARB'); if not Assigned(glGetBufferParameterivARB) then Exit; glGetBufferPointervARB := wglGetProcAddress('glGetBufferPointervARB'); if not Assigned(glGetBufferPointervARB) then Exit; Result := TRUE; end; end; А после инициализации OpenGL делать проверку на наличие данного расширения у видеокарты: JL_USE_VBO := Load_GL_ARB_vertex_buffer_object; Теперь рисование в классе JLGeometry такое. Псевдокод: var me:PJLMesh; me:=Meshes.GetMeshByName(MeshId); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); if JL_USE_VBO then begin glBindBufferARB( GL_ARRAY_BUFFER_ARB, me.VBOpoints[1] ); glNormalPointer( GL_FLOAT, 0, nil ); glClientActiveTextureARB(GL_TEXTURE0_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindBufferARB( GL_ARRAY_BUFFER_ARB, me.VBOpoints[2] ); glTexCoordPointer( 2, GL_FLOAT, 0,nil ); if me.VBOpoints[5]<>0 then begin glClientActiveTextureARB(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindBufferARB( GL_ARRAY_BUFFER_ARB, me.VBOpoints[5] ); glTexCoordPointer( 3, GL_FLOAT, 0,nil ); end; if me.VBOpoints[4]<>0 then begin glClientActiveTextureARB(GL_TEXTURE2_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glBindBufferARB( GL_ARRAY_BUFFER_ARB, me.VBOpoints[4] ); glTexCoordPointer( 3, GL_FLOAT, 0,nil ); end; glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, me.VBOpoints[3] ); glBindBufferARB( GL_ARRAY_BUFFER_ARB, me.VBOpoints[0] ); glVertexPointer( 3, GL_FLOAT, 0, nil ); glDrawElements(GL_TRIANGLES, me.Count, GL_UNSIGNED_INT, nil); end else begin glClientActiveTextureARB(GL_TEXTURE0_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, @ me.Texcoord[0]); glClientActiveTextureARB(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(3, GL_FLOAT, 0, @ me.Tangent[0]); glClientActiveTextureARB(GL_TEXTURE2_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(3, GL_FLOAT, 0, @ me.Binormal[0]); glNormalPointer(GL_FLOAT, 0, @ me.Normal[0]); glVertexPointer(3, GL_FLOAT, 0, @ me.Vertex[0]); glDrawElements(GL_TRIANGLES, me.Count, GL_UNSIGNED_INT, @ me.Indx[0]); end; glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE1_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glClientActiveTextureARB(GL_TEXTURE2_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); Более подробно о том, как изменять и читать данные из VBO вы можете прочитать здесь: http://www.gamedev.ru/community/opengl/articles/?id=5
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
![]() |
![]() |
![]() |
![]() |
Дизайн Elite Games V5 beta.18 EGM Elite Games Manager v5.17 02.05.2010 |
![]() |