Faces Of Nature - Informatyka - C++ Memory Leak
Faces of nature   »  

Informatyka  »   C++ Memory Leak

(1) Najszybsze metody rysowania obiektów

OpenGL daje nam kilka metod pozwalających na wygenerowanie trójkąta na ekranie. Od najprostszych glBegin(); glEnd(); - najmniej optymalnych przez Array Vertex, Display Lists ... do VBO czyli Vertex Buffer Objects, ostatnia metoda umożliwia wykorzystanie pamięci karty graficznej do przechowywania tam upakowanych tablic wierzchołków i tej metodzie się tutaj przyjrzymy.


(2) VBO - Vertex Buffer Objects

Możemy użyć zwykłej upakowanej tablicy wierzchołków Array Vertex albo indeksowanej Index Array Vertex, która pozwala zmniejszyć ilość pamięci przez stworzenie unikalnej tablicy wierzchołków, a przy rysowaniu obiektu przekazaniu jedynie tablicy indeksów tychże wierzchołków - oszczędzamy pamięć, czas przesyłu danych.

I tak np. rysując prostopadłościan złożony z 6 ścian po 2 trójkąty, normalnie przekazalibyśmy zatem 3*2*6 = 36 wierzchołków, a przecież wiele z nich to te same, dlatego tworzymy tablice unikalnych 6 wierzchołków a przy generowaniu wysyłamy jedynie tablice powiedzmy short[6] a nie float[36*3].

Pamiętać należy o tym, że VBO jako standard wystąpił od wersji OpenGL 1.5. A o to co nas czeka:

  1. Stworzenie tablicy wierzchołków i indeksów - dla przykładu weźmy prostokąt:
    struct SVertex
    {
    	float x, y, z;
    	float u, v;
    };
    
    SVertex vertex[] =
    {
    	{ -1.0f, -1.0f, 0.0f,  0.0f, 0.0f },
    	{ -1.0f,  1.0f, 0.0f,  0.0f, 1.0f },
    	{  1.0f,  1.0f, 0.0f,  1.0f, 1.0f },
    	{  1.0f, -1.0f, 0.0f,  1.0f, 0.0f },
    };
    short index[] = { 0, 1, 2, 2, 3, 0 };
    		
  2. Stworzenie Object Buffers dla wierzchołków i załadowanie tam danych
    GLuint VBO_VertexArray;
    glGenBuffers( 1, &VBO_VertexArray );
    glBindBuffer( GL_ARRAY_BUFFER, VBO_VertexArray );
    
    glBufferData( GL_ARRAY_BUFFER, 
    	4 * sizeof(struct SVertex), 
    	vertex, GL_STATIC_DRAW );
    
  3. Stworzenie Object Buffer dla indeksów i załadowanie ich tam
    GLuint VBO_IndicesArray;
    glGenBuffers( 1, &VBO_IndicesArray );
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index );
    
    glBufferData( GL_ELEMENT_ARRAY_BUFFER, 
    	4 * sizeof(short), vertex, GL_STATIC_DRAW );
    
  4. Rysowanie obiektów - najpierw ustawiamy aktualny buffer na ten z wierzchołkami i ustawiamy Pointers odpowiednich danych (vertex, texcoord). Używamy VBO więc jako ostatni argument podajemy offset w wcześniej wysłanej tam tablicy. A jako że współrzędne UV są zaraz za wierzchołkami - a dokładnie 3*sizeof(float) dalej więc podajemy tylko tą różnicę (uwzględniając wskaźnik NULL - który i tak na większości platform jest ustawiony na 0). A następnie ustawiamy buffer indeksów i rysujemy!
    
    glBindBuffer( GL_ARRAY_BUFFER_ARB, VBO_VertexArray );
    glVertexPointer(3, GL_FLOAT, sizeof(struct SVertex), 
    	(GLvoid*)NULL);
    glTexCoordPointer(2, GL_FLOAT, sizeof(struct SVertex), 
    	(GLvoid*)((float*)NULL + 3) );
    			
    glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, VBO_IndicesArray );
    glDrawRangeElements( GL_TRIANGLES, 0, 6, 6, 
    	GL_UNSIGNED_SHORT, (GLvoid *)NULL);
    

(3) Vertex Array

VBO spisują się w przypadku statycznych obiektów, gdy mamy do czynienia z obiektami często zmieniającymi swe dane (np. wierzchołki - animacja) wtedy stosujemy tzw. mixy, np. tablice z współrzędnymi tekstur wrzucamy do VBO a wierzchołki generujemy za pomocą Vertex Array.

Albo gdy klient posiada wersję OpenGL <1.5. Poniżej przykład generowania tego prostokąta, ale bez VBO.


	glVertexPointer(3, GL_FLOAT, 
		sizeof(struct SVertex), vertex);
		
	glTexCoordPointer(2, GL_FLOAT, 
		sizeof(struct SVertex), (float *)vertex + 3);
		
	glDrawElements( GL_TRIANGLES, 6, 
		GL_UNSIGNED_SHORT, index);

Przykład do ściągnięcia:
Potrzebna będzie biblioteka glew.dll, aby móc używać m.in. własnie VBO

Faces of nature   »  

Informatyka  »   C++ Memory Leak