2015-01-30 15 views
6

Przedtem napisałem pytanie o to, jak uzyskać działanie OpenGL na Qt, ale teraz chcę mieć możliwość korzystania z najnowszych funkcji OpenGL do użycia. Przed Qt używałem glew; ale Qt mówi, że glew jest w konflikcie z plikiem nagłówkowym QtOpenGL. Zajrzałem do QGLWidget i QGLFunctions, ale mówiąc szczerze, jestem zdezorientowany co do tego, co naprawdę powinienem robić, aby uzyskać dostęp do funkcji OpenGL.Używanie najnowszych funkcji OpenGL w klasach w Qt 5.4

Teraz mam Qt 5.4 przy użyciu Qt Creator 3.3.0 i korzystam z nowego QOpenGLWidget; jednak brak wskazówek co do tego, w jaki sposób powinien być użyty, rzuca mi trochę: dokumentacja Qt jest tam i pomaga, ale demonstruje tylko jak ją utworzyć, zamiast jej używać w innych lokalizacjach programu. Rozumiem, że ta QOpenGLWidget działa podobnie do QGLWidget. Qt szczegóły, które powinienem dziedziczyć; jednak nie tworzę instancji kontekstu OpenGL w klasie, która chce używać funkcji OpenGL; dzieje się to w klasie "glWidget", która dziedziczy po QOpenGLWidget.

Weźmy na przykład ten fragment z jednego z moich klas, które wykorzystuje kod OpenGL:

void Mesh::init() 
{ 
    pNumIndices = pIndices.size(); 

    glGenVertexArrays(1, &pVAO); 
    glGenBuffers(1, &pVertexBuffer); 
    glGenBuffers(1, &pIndexBuffer); 
    glBindVertexArray(pVAO); 

    glBindBuffer(GL_ARRAY_BUFFER, pVertexBuffer); 
    glBufferData(GL_ARRAY_BUFFER, pVertices.size() * sizeof(Vertex), 
       &pVertices[0], GL_STATIC_DRAW); 

    // etc.. 
} 

Mesh jest klasa, która nie dziedziczy od wszystkiego. Oryginalnie używał tylko polecenia, aby uzyskać deklaracje funkcji OpenGL; nie musiała wiedzieć, czy są ważne, czy nie, bo to jest robota. Potem w klasie mainApp bym wystąpił z instancją. Rozumiem również, że istnieje również klasa QOpenGLFunctions, która działa trochę podobnie do tej z glew, ale w przypadku wszystkich tych klas GL jest rażąco mylące wiedzieć, czego używać. Co więcej, próbowałem szukać glGenVertexArrays (..), ale nie znaleziono go w QOpenGLBuffer, QOpenGLFunctions lub QOpenGLWidget; i o ile mi wiadomo, tak jak w OpenGL 4.5 nadal jest częścią specyfikacji; ale moje sterowniki graficzne nie używają OpenGL 4.5, więc używam OpenGL 4.3. Wystarczy powiedzieć, że jestem gotów zrezygnować z dmuchania, aby przyjąć własne podejście Qt do wywoływania funkcji OpenGL.

W programie, w którym różne klasy używają funkcji OpenGL, w jaki sposób mogę wykorzystać Qt, aby móc do nich zadzwonić bez użycia glew? Siatka jest jedną z tych klas, która nie tworzy instancji OpenGL, ale jedynie wykorzystuje jej funkcje.

Po to, aby ludzie wiedzieli, używam Qt przez jakiś czas (nie wystarczy!) I cieszę się Qt; ale muszę wiedzieć, jak używać Qt w połączeniu z OpenGL, aby kontynuować rozwój. Większość tutoriali nadal używa rzeczy sprzed 5.4.

+1

'glGenVertexArrays' jest dla obiektów tablicy wierzchołek, tak Jaka jest nazwa klasy, której powinieneś szukać? Zgadza się, ['QOpenGLVertexArrayObject'] (http://doc.qt.io/qt-5/qopenglvertexarrayobject.html)! – peppe

+0

Osobiście nie lubię rzeczy Q, w których centralnie zajmuje się materiałami OpenGL. Bardzo lubię robić takie rzeczy sam z moimi własnymi zajęciami. – Poriferous

Odpowiedz

4

w Qt 5.4, są nagłówki z wersją określonych funkcji OpenGL, więc:

#include <QOpenGLFunctions_3_3_Core> 

Albo cokolwiek wersja chcesz użyć.Potem gdzieś z ważnego kontekstu OpenGL jak QOpenGLWidget :: initializeGL() tworzenia i zainicjować obiektu QOpenGLFunctions:

QOpenGLFunctions_3_3_Core *fun = new QOpenGLFunctions_3_3_Core; 
fun->initializeOpenGLFunctions(); 

, a następnie w kodzie losowania, wystarczy użyć funkcji OpenGL z tego obiektu:

fun->glSomething(1,2,3) 
+3

Inną opcją jest * dziedziczenie * z takiej klasy, więc możesz po prostu napisać 'glSomething' i to zadziała. – peppe

+0

Okay, a jeśli mam inną klasę, która nie jest QOpenGLWidget, ale używa funkcji OpenGL 4.3, co mam zrobić? – Poriferous

+0

Utwórz obiekt QOpenGLFunctions_3_3_Core lub wypróbuj go. Nic nie zależy od QOpenGLWidget w żaden sposób. Po zainicjowaniu potrzebujesz tylko aktualnego kontekstu OpenGL. – wrosecrans

1

Prosta podejście z OpenGL jest stworzenie struktury zawierające wskaźników funkcji:

struct sLGLAPI 
{ 
    sLGLAPI() { memset(this, 0, sizeof(*this)); }; 
    PFNGLACTIVETEXTUREPROC  glActiveTexture; 
    PFNGLATTACHSHADERPROC  glAttachShader; 
    PFNGLBEGINQUERYPROC   glBeginQuery; 
    PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation; 
    ... 

wypełnić go ze wskaźnikami dlsym -ED z udostępnionej biblioteki OpenGL:

API->glActiveTexture = (PFNGLACTIVETEXTUREPROC)GetGLProc("glActiveTexture"); 
API->glAttachShader = (PFNGLATTACHSHADERPROC)GetGLProc("glAttachShader"); 
API->glBeginQuery = (PFNGLBEGINQUERYPROC)GetGLProc("glBeginQuery"); 
API->glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)GetGLProc("glBindAttribLocation"); 

i dostęp OpenGL w twojej kodu tylko poprzez tę strukturę. Na przykład:

API->glShaderSource(Shader, 1, &Code, nullptr); 
API->glCompileShader(Shader); 

ten sposób będziesz w stanie ukryć kompletny OpenGL API, a nawet w razie potrzeby wykorzystać funkcje pośredniczące, na przykład, parametry logowania lub do przełączania między OpenGL i OpenGL ES.

+0

Twoje rozwiązanie jest trafne; ale dlsym jest dostępny tylko w systemie Linux i podobnych systemach. Używam też Linuksa; ale muszę również uruchomić mój kod pod Windows. Czy Qt nie miałby wieloplatformowego sposobu obsługi tego zadania? – Poriferous

+1

@Poriferous GetProcAddress jest najbliższy dlsymu – BlamKiwi

+0

To nie jest rozwiązanie, którego szukam, równie interesujące, jak się wydaje; Potrzebuję czegoś bardziej zgodnego z Qt. – Poriferous

1
#include <QOpenGLFunctions_3_3_Core> 

class Mesh : public QOpenGLFunctions_3_3_Core 
{ 
public: 
    Mesh();//initializeOpenGLFunctions() 
    ~Mesh();  

    void func();//glxxx in it. when using it ,you need an opengl context. 
       //for example, use makeCurrent() in QOpenGLWidget subclass. 
}; 
1

Używanie QOpenGLFunctions_X_X_ * nie rozwiąże tego problemu! Musisz ustawić wersję kontekstu OpenGL, zanim będziesz mógł użyć QOpenGLFunctions_X_X_ *. Qt użyć wersji domyślnej (myślę 1.X), więc trzeba dodać ten kod do pliku main.cpp

 QSurfaceFormat format; 
//  format.setDepthBufferSize(24); 
    // format.setStencilBufferSize(8); 

     format.setMajorVersion(3); //whatever version 
     format.setMinorVersion(3); // 
     format.setProfile(QSurfaceFormat::CoreProfile); 
     QSurfaceFormat::setDefaultFormat(format); 

Cheers, Nai