Учебник по Visual C++ .Net

         

Подготовка окна Вы помните, что


CView::PreCreateWindow(cs);

}

Вы помните, что окно OpenGL не должно позволять Windows стирать свой фон, так как данная операция сильно тормозит работу конвейера. В связи с этим введите в функцию обработки WM_ERASEBKGND код, сообщающий системе, что сообщение уже обработано:

BOOL COGView::OnEraseBkgnd(CDC* pDC)

{

return TRUE;

}

Окно OpenGL имеет свой собственный формат пикселов. Нам следует выбрать и установить подходящий формат экранной поверхности в контексте устройства HDC, а затем создать контекст передачи изображения (HGLRC). Для описания формата пикселов экранной поверхности используется структура PIXELFORMATDESCRIPTOR. Выбор формата зависит от возможностей карты и намерений разработчика. Мы зададим в полях этой структуры такие настройки:

  • глубину цвета — 24;

  • тип буферизации — двойной;

  • схему образования цвета RGBA;

  • количество бит для буфера глубины — 32;

  • поддержку регулировки прозрачностью и другие специфические настройки выключим.

    В функцию OnCreate введите код подготовки окна OpenGL. Работа здесь ведется со структурой PIXELFORMATDESCRIPTOR. Кроме того, в ней создается контекст m_hRC и устанавливается в качестве текущего:

    int COGView::OnCreate(LPCREATESTROCT IpCreateStruct)

    {



    if (CView::OnCreate(IpCreateStruct) == -1)

    return -1;

    PIXELFORMATDESCRIPTOR pfd = // Описатель формата

    {

    sizeof(PIXELFORMATDESCRIPTOR), // Размер структуры

    1, // Номер версии

    PFD_DRAW_TO_WINDOW | // Поддержка GDI

    PFD_SUPPORT_OPENGL | // Поддержка OpenGL

    PFD_DOUBLEBUFFER, // Двойная буферизация

    PFD_TYPE_RGBA, // Формат RGBA, не палитра

    24, // Количество плоскостей

    //в каждом буфере цвета

    24, 0, // Для компонента Red

    24, 0, // Для компонента Green

    24, 0, // Для компонента Blue

    24, 0, // Для компонента Alpha

    0, // Количество плоскостей

    // буфера Accumulation

    0, // То же для компонента Red

    0, // для компонента Green

    0, // для компонента Blue

    0, // для компонента Alpha

    32, // Глубина 2-буфера

    0, // Глубина буфера Stencil


    0, // Глубина буфера Auxiliary

    0, // Теперь игнорируется

    0, // Количество плоскостей

    0, // Теперь игнорируется

    0, // Цвет прозрачной маски

    0 // Теперь игнорируется };

    //====== Добываем дежурный контекст

    m_hdc = ::GetDC(GetSafeHwnd());

    //====== Просим выбрать ближайший совместимый формат

    int iD = ChoosePixelForraat(m_hdc, spfd);

    if ( !iD )

    {

    MessageBoxC'ChoosePixelFormat: :Error") ;

    return -1;

    }

    //====== Пытаемся установить этот формат

    if ( ISetPixelFormat (m_hdc, iD, Spfd) )

    {

    MessageBox("SetPixelFormat::Error");

    return -1;

    }

    //====== Пытаемся создать контекст передачи OpenGL

    if ( !(m_hRC = wglCreateContext (m_hdc)))

    {

    MessageBox("wglCreateContext::Error");

    return -1;

    }

    //====== Пытаемся выбрать его в качестве текущего

    if ( IwglMakeCurrent (m_hdc, m_hRC))

    {

    MessageBox("wglMakeCurrent::Error");

    return -1;

    //====== Теперь можно посылать команды OpenGL

    glEnable(GL_LIGHTING); // Будет освещение

    //====== Будет только один источник света

    glEnable(GL_LIGHTO);

    //====== Необходимо учитывать глубину (ось Z)

    glEnable(GL_DEPTH_TEST);

    //====== Необходимо учитывать цвет материала поверхности

    glEnable(GL_COLOR_MATERIAL);

    //====== Устанавливаем цвет фона .

    SetBkColor () ;

    //====== Создаем изображение и запоминаем в списке

    DrawScene () ;

    return 0;

    }

    Контекст передачи ( rendering context) создается функцией wglCreateContext с учетом выбранного формата пикселов. Так осуществляется связь OpenGL с Windows. Создание контекста требует, чтобы обычный контекст существовал и был явно указан в параметре wglCreateContext. HGLRC использует тот же формат пикселов, что и НОС. Мы должны объявить контекст передачи в качестве текущего (current) и лишь после этого можем делать вызовы команд OpenGL, которые производят включение некоторых тумблеров в машине состояний OpenGL. Вызов функции DrawScene, создающей и запоминающей изображение, завершает обработку сообщения. Таким образом, сцена рассчитывается до того, как приходит сообщение о перерисовке WM_PAINT. Удалять контекст передачи надо после отсоединения его от потока. Это делается в момент, когда закрывается окно представления. Введите в тело заготовки OnDestroy следующие коды:



    void COGView::OnDestroy(void)

    {

    //====== Останавливаем таймер анимации

    KillTimer(1);

    //====== Отсоединяем контекст от потока

    wglMakeCurrent(0, 0); //====== Удаляем контекст

    if (m_hRC)

    {

    wglDeleteContext(m_hRC);

    m_hRC = 0;

    }

    CView::OnDestroy() ;

    }

    Так же как и в консольном проекте OpenGL, обработчик сообщения WM_SIZE должен заниматься установкой прямоугольника просмотра (giviewport) и мы, так же как и раньше, зададим его равным всей клиентской области окна. -Напомним, что конвейер OpenGL использует эту установку для того, чтобы поместить изображение в центр окна и растянуть или сжать его пропорционально размерам окна. Кроме того, в обработке onSize с помощью матрицы проецирования (GL_PROJECTION) задается тип проекции трехмерного изображения на плоское окно. Мы выбираем центральный или перспективный тип проецирования и задаем при этом угол зрения равным m_AngleView. В конструкторе ему было присвоено значение в 45 градусов:

    void COGView::OnSize(UINT nType, int ex, int cy)

    {

    //====== Вызов родительской версии

    CView::OnSize(nType, ex, cy) ;

    //====== Вычисление диспропорций окна

    double dAspect = cx<=cy ? double(cy)/ex : double(ex)/cy;

    glMatrixMode (GL_PROJECTION) ;

    glLoadldentity() ;

    //====== Установка режима перспективной проекции

    gluPerspective (m_AngleView, dAspect, 0.01, 10000.);

    //====== Установка прямоугольника просмотра

    glViewport(0, 0, сх, су);

    }


    Содержание раздела