QOpenGLFunctions的相關的使用(1)


QOpenGLFunctions的使用

1.  QOpenGLFunctions  說明

   QOpenGLFunctions 類提供了跨平台的OpenGl ES2.0 API版本。

  OpenGL 2.0 提供了OpenGL中的子類集合,可以提供跨多個平台的桌面系統以及嵌入式OpenGL的實現。然而,卻很難使用子類因為子類需要解決許多平台系統的操作問題。

  因此 QOpenGLFunctions提供了這樣的API,可以保證在所有的OpenGL系統中使用,並且也關注不同系統中的OpenGL的版本API的使用。Qt推薦直接繼承的方式來使用 QOpenGLFunctions類。

2.  QOpenGLFunctions 使用

class MyGLWindow : public QWindow, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    MyGLWindow(QScreen *screen = 0);

protected:
    void initializeGL();
    void paintGL();

    QOpenGLContext *m_context;
};

MyGLWindow(QScreen *screen)
  : QWindow(screen), QOpenGLWidget(parent)
{
    setSurfaceType(OpenGLSurface);
    create();

    // Create an OpenGL context
    m_context = new QOpenGLContext;
    m_context->create();

    // Setup scene and render it
    initializeGL();
    paintGL()
}

void MyGLWindow::initializeGL()
{
    m_context->makeCurrent(this);
    initializeOpenGLFunctions();
}

  paintGL函數中可以使用任意的Opengl ES 2.0 API且不需要明確聲明。如直接使用glActiveTexture():

  written by www.icmzn.com

void MyGLWindow::paintGL()
{
    m_context->makeCurrent(this);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, textureId);
    ...
    m_context->swapBuffers(this);
    m_context->doneCurrent();
}

  An alternative approach is to query the context's associated QOpenGLFunctions instance. This is somewhat faster than the previous approach due to avoiding the creation of a new instance, but the difference is fairly small since the internal data structures are shared, and function resolving happens only once for a given context, regardless of the number of QOpenGLFunctions instances initialized for it.

  可選的方式是查找當前環境關聯的QOpenGLFunctions實例, 這比之前快,因為避免了新實例的創建。但是,差異不大因為內部數據結構是共享的,且函數解析往往只在給定的環境中調用一次。

QOpenGLFunctions *glFuncs = QOpenGLContext::currentContext()->functions();
glFuncs->glActiveTexture(GL_TEXTURE1);

  QOpenGLFunctions provides wrappers for all OpenGL ES 2.0 functions, including the common subset of OpenGL 1.x and ES 2.0. While such functions, for example glClear() or glDrawArrays(), can be called also directly, as long as the application links to the platform-specific OpenGL library, calling them viaQOpenGLFunctions enables the possibility of dynamically loading the OpenGL implementation.

  QOpenGLFunctions 提供了對OpenGL ES2.0 包裝。包括f OpenGL 1.x and ES 2.0.的子類。只要應用程序鏈接到指定平台的Opengl庫中個,則可以直接調用相應的API,通過借助於QOpenGLFunctions 可以確保能夠動態加載Opengl的實現庫。

 

3. 不同版本的 QOpenGLFunctions

  The QAbstractOpenGLFunctions class is the base class of a family of classes that expose all functions for each OpenGL version and profile.

   QAbstractOpenGLFunctions 類提供了對每個Opengl版本的API函數的基本集合。

  OpenGL implementations on different platforms are able to link to a variable number of OpenGL functions depending upon the OpenGL ABI on that platform. For example, on Microsoft Windows only functions up to those in OpenGL 1.1 can be linked to at build time. All other functions must be resolved at runtime. The traditional solution to this has been to use either QOpenGLContext::getProcAddress() or QOpenGLFunctions. The former is tedious and error prone and means dealing directly with function pointers. The latter only exposes those functions common to OpenGL ES 2 and desktop OpenGL. There is however much new OpenGL functionality that is useful when writing real world OpenGL applications.

  OpenGL 實現不同平台上的相應的API,因為其可以直接連接到相應平台上的API接口。如在微軟系統中,只能提供Opengl 1.1 接口使用。其他的函數必須在運行時解析。傳統的解決方法是使用 QOpenGLContext::getProcAddress() or QOpenGLFunctions. 前者直接操作相應的函數指針,因此乏味且容易出錯。后者則展示了嵌入式Opengl ES 2 和桌面Opengl的公共接口函數。則在使用Opengl 應用顯示渲染時,足夠新的函數API。

  Qt now provides a family of classes which all inherit from QAbstractOpenGLFunctions which expose every core OpenGL function by way of a corresponding member function. There is a class for every valid combination of OpenGL version and profile. Each class follows the naming convention:

  Qt 現在提供了繼承自的 QAbstractOpenGLFunctions大家族, 都提供了OpenGl 核心函數對應相應的函數版本。因此對應每個有效的Opengl版本都有相應的類。且每個類遵循下述規約:

  上述每個類都繼承自 QAbstractOpenGLFunctions  。其中Opengl 3.1 移除了大量的deprecated 函數,因此足夠簡潔且更加通用的API。而對於Opengl 3.2 ,則采用了定義兩種類的方式: Opengl 3.2 core 以及 Opengl 3.2 Compatibility。

  對於Core類型的類,則其不包含在前一版本Opengl 3.1中摒棄的函數API;對於Compatibility 類型的類,則其包含所有的函數API在core版本,以及相應的前一版本Opengl 3.1中並且的函數API。通過這樣的方法,Compatibility 的類允許用戶使用新版本的Opengl,但是也可以保持使用合法的core API . 因此推薦使用 Core的類。

  但是需要注意的是,對於API接口實現,如蘋果公司,沒有實現顯影的Compatibility的類,因此,如果你希望使用新的Opengl的API在OSX系統中,你應該確保你使用Core 類通過借助於QSurfaceFormat::setProfile()

  Qt 提供了多有版本與Core以及Compatibility的實現,對於Opengl版本Opengl 3.1 到Opengl 4.3,如下所示:

  A pointer to an object of the class corresponding to the version and profile of OpenGL in use can be obtained from QOpenGLContext::versionFunctions(). If obtained in this way, note that the QOpenGLContext retains ownership of the object. This is so that only one instance need be created.

QAbstractOpenGLFunctions * QOpenGLContext::versionFunctions(const QOpenGLVersionProfile &versionProfile = QOpenGLVersionProfile()) const

  函數 QOpenGLContext::versionFunctions可以返回對於該環境中versionProfile相應的QAbstgractOpenglFuncation指針。在使用人一個API之前,需要通過使用當前環境變量通過該函數 QAbstractOpenGLFunctions::initializeOpenGLFunctions()來初始化,然后才能使用。注意:如果這樣使用,則當前的Opengl環境變量則仍然是返回的對象指針所致的Object。這是因為只能有一個instance創建。

  Before calling any of the exposed OpenGL functions you must ensure that the object has resolved the function pointers to the OpenGL functions. This only needs to be done once per instance with initializeOpenGLFunctions(). Once initialized, the object can be used to call any OpenGL function for the corresponding version and profile. Note that initializeOpenGLFunctions() can fail in some circumstances so check the return value. Situations in which initialization can fail are if you have a functions object for a version or profile that contains functions that are not part of the context being used to resolve the function pointers.

  在調用任何的OpenGL functions之前,必須要確保當前的Object已經解決了函數指針指向Opengl 函數的問題。這只需要在初始化initializeOpenGLFunctions()時,執行一次。一旦初始化, 當前的對象Object能夠使用來調用Opengl 的API 到相應的版本中。注意:在一些環境中,初始化initializeOpenGLFunctions()也會發生調用失敗的情況,因此來檢查返回的值。如對於使用的版本不兼容當前的環境的情況下,就會初始化失敗。

  If you exclusively use function objects then you will get compile time errors if you attempt to use a function not included in that version and profile. This is obviously a lot easier to debug than undefined behavior at run time.

  如果你僅僅(只,獨家)使用函數Object,如果你調用該函數對象之外的版本API,則將會返回兼容的異常。

TYPE * QOpenGLContext::versionFunctions() const

  該函數則返回當前環境中的函數版本的函數對象指針。同時,也要在使用之前調用initializeOpenGLFunctions來再次初始化該函數對象,將該對象重新綁定到當前的環境實例中。

  一般都是來使用該函數的模板類型,從而可以自動轉換為正確的函數來行。因此是可以請求一個不同版本的函數對象,即與當前環境對象中的函數對象不同。即如下圖采用模板方法來獲取指定的函數對象版本。

 代碼示例:

QOpenGLFunctions_3_3_Core* funcs = 0;
funcs = context->versionFunctions<QOpenGLFunctions_3_3_Core>();
if (!funcs) {
    qWarning() << "Could not obtain required OpenGL context version";
    exit(1);
}
funcs->initializeOpenGLFunctions();

  注意:請求其他不同的函數對象也可能會調用失敗,並且返回NULL空指針,即請求不滿足當前使用環境中的函數對象。例如:

  • Requesting a 3.3 core profile functions object would succeed.
  • Requesting a 3.3 compatibility profile functions object would fail. We would fail to resolve the deprecated functions.
  • Requesting a 4.3 core profile functions object would fail. We would fail to resolve the new core functions introduced in versions 4.0-4.3.
  • Requesting a 3.1 functions object would succeed. There is nothing in 3.1 that is not also in 3.3 core.

 

4. 使用某一個版本的QOpenGLFunctions

    QOpenGLFunctions_2_1 ,提供了OpenGL 2.1 的規范。即其包裝了Opengl2.1 的規范,可以直接使用Opengl2.1 的API。

 

endl;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM