1

OpenGL ウィンドウの作成時に実行される最初のイベント ハンドラーが OnCreateであると仮定して、ここで codeguru から COpenGLControl クラスをダウンロードしたとします。このクラスのエラーをキャッチしようとしました。ダイアログの .h および .cpp ファイルでウィンドウを作成するために使用されるコードは次のとおりです。

MyOpenGLTestDlg.h

COpenGLControl m_oglWindow;  

MyOpenGLTestDlg.cpp

CRect rect;

// Get size and position of the picture control
GetDlgItem(ID_OPENGL)->GetWindowRect(rect);

// Convert screen coordinates to client coordinates
ScreenToClient(rect);  

OnCreate関数が呼び出されたと思います。COpenGLControl m_oglWindow;実際、コード行によってこの関数が呼び出されると思います! しかし、よくわからないので、これについて少し教えていただければ幸いです。
とにかく、私はクラスに多くの変更を加えていません:

OpenGLControl.h

#pragma once
#include "afxwin.h"
#include "WinBase.h"

#include <gl/gl.h>
#include <gl/glu.h>

class COpenGLControl : public CWnd
{
public:
    /******************/
    /* Public Members */
    /******************/
    UINT_PTR m_unpTimer;
    // View information variables
    float    m_fLastX;
    float    m_fLastY;
    float    m_fPosX;
    float    m_fPosY;
    float    m_fZoom;
    float    m_fRotX;
    float    m_fRotY;
    bool     m_bIsMaximized;

private:
    /*******************/
    /* Private Members */
    /*******************/
    // Window information
    CWnd  *hWnd;     //window handle
    HDC   hdc;       //device context handle    
    HGLRC hrc;       //handle to GL Rendering Context
    int   m_nPixelFormat;
    CRect m_rect;
    CRect m_oldWindow;
    CRect m_originalRect;

public:
    COpenGLControl(void);
    virtual ~COpenGLControl(void);

    void oglCreate(CRect rect, CWnd *parent);
    void oglInitialize(void);
    void oglDrawScene(void);

    // Added message classes:
    afx_msg void OnPaint();
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnDraw(CDC *pDC);
    afx_msg int  OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnTimer(UINT nIDEvent);
    afx_msg void OnMouseMove(UINT nFlags, CPoint point);

    DECLARE_MESSAGE_MAP()
};  

OpenGLControl.cpp

int COpenGLControl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CWnd::OnCreate(lpCreateStruct) == -1) return -1;

    oglInitialize();

    return 0;
}  
void COpenGLControl::oglInitialize(void)
{
    // Initial Setup:
    //
    static PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32, // bit depth
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        24, // z-buffer depth
        8,0,PFD_MAIN_PLANE, 0, 0, 0, 0,
    };

    // Get device context only once.
    hdc = GetDC()->m_hDC;
    // Pixel format.
    m_nPixelFormat = ChoosePixelFormat(hdc, &pfd);
    SetPixelFormat(hdc, m_nPixelFormat, &pfd);
    // Create the OpenGL Rendering Context.
    hrc = wglCreateContext(hdc);
    GLenum error13 = glGetError();
    wglMakeCurrent(hdc, hrc);

   // Basic Setup:
   //
   // Set color to use when clearing the background.
   glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
   glClearDepth(1.0f);
   // Turn on backface culling
   glFrontFace(GL_CCW);
   glCullFace(GL_BACK);
   // Turn on depth testing
   glEnable(GL_DEPTH_TEST);
   glDepthFunc(GL_LEQUAL);
   // Send draw request
   OnDraw(NULL);
}  

GLenum error13 = glGetError();ご覧のとおり、スローされる可能性のあるエラーをキャッチするために直後にコードを書きました。hrc = wglCreateContext(hdc);はい、error13 の値は、1282つまり、適切に作成されていないINVALID_OPERATIONと思いhandle for OpenGL rendering contextます!
さらに、 との値を確認するhdchrc、次のことがわかります。

hdc -> 未使用 = ??? (エラー: 式を評価できません)
hrc -> 未使用 = 0

なぜそうなのかを知るのを手伝ってもらえますか?問題は何ですか?

4

2 に答える 2

2

Win32 で呼び出しスレッドの「現在のコンテキスト」を取得する前に、OpenGL API 関数を呼び出さないでください。操作は未定義になります。

この問題を修正するには、コールをwglMakeCurrent (...)1 行上に移動して、 へのコールの前に来るようにしglGetError (...)ます。

すべてのスレッドに対してこれを行う必要があることに注意してください。Win32 では、任意の時点で 1 つのスレッドのみが OpenGL コンテキストにアクセスできます。Win32 でマルチスレッド レンダリングを実行したい場合は、コンテキストを取得/解放してスレッド間の同期を行うか、「リストを共有する」一連のコンテキストを使用する必要があります ( wglShareLists (...))。

derhass が述べたように、WGL API によって生成されたエラーに関する情報が必要な場合は、GetLastError (...). WGL は、Win32 API の上に構築されたウィンドウ システムの一部であるため、従来の Win32 チャネルを介してエラーを通知します。


ところで、GL エラー値を 10 進数形式で出力しないようにしてください。これらは常に gl.h で 16 進数の定数として列挙されるため、次のようにすると適切な列挙子を簡単に見つけることができます。

printf ("OpenGL Error: 0x%X\n", err);

同じことが、OpenGL のすべての列挙型定数にも当てはまります。それらを人間が読める文字列にマップする関数がない場合は、16 進値を使用して検索する必要があります。

于 2013-08-16T21:24:23.213 に答える
2

glGetError()現在の GL コンテキストを持たずにGL 関数 (それ自体など) を呼び出した場合、結果はまったく定義されていません。

wglCreateContext()Win33 API (GL API ではない) の一部であり、NULLポインターを返すことでエラーを通知します。GetLastError()その場合の詳細が必要な場合は、他のほとんどの Windows API 関数と同様に、Windows API 関数を呼び出すことができます。

于 2013-08-16T19:09:09.493 に答える