0

私はシェーダーとOpenGlをwxWidgetsプログラムに組み込んでみました。私は以下のリンクを使用しました:

http://nehe.gamedev.net/article/glsl_an_introduction/25007/

http://www.lighthouse3d.com/tutorials/glsl-tutorial/hello-world-in-glsl/

今、私はテストプログラムで、lighthouse3dチュートリアルによって提供されるシェーダーを使用して、出力を再作成しようとしています(白い背景でゆっくりと回転する青いティーポット)。でも何も描くことができないようで、見えるのは黒い画面だけです。これまでの私のコードは以下のとおりです(99%確実に問題がないため、最初はほとんどのシェーダーを無視します):

void BasicGLPane::render( wxPaintEvent& evt )
{
    //wxGLCanvas::SetCurrent(*m_context);
    wxPaintDC(this); 
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    //prepare2DViewport(0,0,getWidth()/2, getHeight());
    glLoadIdentity();
    gluLookAt(0.0,0.0,5.0, 
          0.0,0.0,-1.0,
          0.0f,1.0f,0.0f);

    glLightfv(GL_LIGHT0, GL_POSITION, lpos);
    //glRotatef(a,0,1,1);
    glutSolidTeapot(1);
    glFlush();
    //a+=0.1;

    SwapBuffers();
}

void BasicGLPane::InitializeGLEW()
{
    //prepare2DViewport(0,0,getWidth(), getHeight());
    // The current canvas has to be set before GLEW can be initialized.
    wxGLCanvas::SetCurrent(*m_context);
    GLenum err = glewInit();

    // If Glew doesn't initialize correctly.
    if(GLEW_OK != err)
    {
        std::cerr << "Error:" << glewGetString(err) << std::endl;
        const GLubyte* String = glewGetErrorString(err);
        wxMessageBox("GLEW is not initialized");
    }

BasicGLPane::BasicGLPane(wxFrame* parent, int* args) :
wxGLCanvas(parent, wxID_ANY, args, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE)
{

    m_context = new wxGLContext(this);

    // To avoid flashing on MSW
    SetBackgroundStyle(wxBG_STYLE_CUSTOM);
}

なぜ出力が得られないのか考えてきました。私が持っている考えの1つは、m_contextと関係があります。GLEWを実行する前に、WxWidgetsの現在のコンテキストを設定する必要があります。チュートリアルで初期化されるプロパティもいくつかありますが、wxWidgetsバージョンではこれらの関数を使用していないので、使用する必要があるかどうか疑問に思っています。これらは:

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(320,320);
glutCreateWindow("MM 2004-05");

glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glutKeyboardFunc(processNormalKeys);

glEnable(GL_DEPTH_TEST);
glClearColor(1.0,1.0,1.0,1.0);
glEnable(GL_CULL_FACE);

しかし、私は過剰使用を避けることに非常に熱心であり、今までそれを回避することができました。以前に追加した唯一の理由は、チュートリアルの動作を再現することです。

編集:

1ビットまたは2ビットの奇妙な動作に気付いたので、もう少し追加します。ドローでこの関数を呼び出すと、次のようになります。

void BasicGLPane::prepare2DViewport(int topleft_x, int topleft_y, int bottomrigth_x, int bottomrigth_y)
{
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f); // Black Background
    glEnable(GL_TEXTURE_2D);   // textures
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_BLEND);
    glDisable(GL_DEPTH_TEST);
    glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

    glViewport(topleft_x, topleft_y, bottomrigth_x-topleft_x, bottomrigth_y-topleft_y);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluOrtho2D(topleft_x, bottomrigth_x, bottomrigth_y, topleft_y);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

ウィンドウサイズを変更すると、背景の色を変更できます。また、すべてのフレームを更新するわけではありません。1つのフレームのみを描画し、ウィンドウサイズを変更するまでレンダリング関数を再度呼び出すことはありません。

4

2 に答える 2

0

これまでのところ、コードは良さそうです。多くのチュートリアルで見つかることの1つですが、悪い習慣は、明らかに初期化が行われていることです。これはそうではありません。OpenGLは初期化されていません。これはステートマシンであり、必要なときに状態を設定する必要があります。台詞

glEnable(GL_DEPTH_TEST);
glClearColor(1.0,1.0,1.0,1.0);
glEnable(GL_CULL_FACE);

描画機能に完全に満足しています。また、プロジェクションを設定する必要があります。チュートリアルでは、ウィンドウサイズ変更ハンドラーで設定されることがよくあります。この悪い習慣に陥らないでください。投影とビューポートは描画状態ですので、描画機能で設定してください。

OpenGL-3(コアプロファイル)以降を使用している場合は、少なくとも頂点フラグメントシェーダーを指定する必要があります。古いバージョンでは、各シェーダーステージはオプションであり、固定機能とプログラム可能なパイプライン間の通信の共通の基盤を提供するための組み込み変数があります。ただし、混合操作は強くお勧めしません。常にシェーダーを使用し、頂点シェーダーとフラグメントシェーダーの両方を使用します。長期的には、それらは物事をすっごく簡単にします。

于 2013-01-12T21:48:53.043 に答える
0

レンダリングにgluLookAtは必要ありませんでした。

于 2013-01-14T15:50:09.980 に答える