FP OpenGL example почему пропадает картинка?

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

FP OpenGL example почему пропадает картинка?

Сообщение xterro » 03.09.2015 11:48:06

Доброго времени суток, здесь на сайте, в разделе "статьи", есть примеры работы с opengl на FP. Взял первый пример, собрал, всё работает, но есть некоторая проблема: при перемещении окна или изменении его размера, изображение в окне "пропадает" и оно закрашивается цветом:
Код: Выделить всё
WindowClass.hbrBackground   := GetStockObject(WHITE_BRUSH);

как этого избежать?

Код: Выделить всё

{$MODE objfpc}{$H+}
//{$APPTYPE GUI}

program ogl_fpc_source01;

uses
    {$ifdef windows} 
    windows,
    {$endif}
    gl, glu;

var

    msg : TMSG;      // Windows messages
    hWindow : HWnd;   // Windows Handle to the OGL Window
    dcWindow : hDc;   // Device Context for the OGL Window
    rcWindow : HGLRC;   // Render Context for the OGL Window

    width, height, bits : longint;
    fullscreen, active : boolean;

   
   
   
// Simple OGL initialisation for testing. //
procedure OpenGL_Init();
begin
    glShadeModel(GL_SMOOTH);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glClearColor( 0.0, 0.0, 0.0, 1.0 );
   // glTranslatef(0.0, 0.0, 0.0);
   
end;

function OpenGL_Render() : boolean;
begin
    glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
   
    { draw here }
   
    glClear( GL_COLOR_BUFFER_BIT );
  glLoadIdentity();
  glTranslatef(0.9,0.0,0.0);
  glBegin( GL_TRIANGLES );
    glColor3f(1.0, 0.0, 0.0); 
     glVertex3f(0.0, 1.0, 0.0);
    glColor3f(0.0, 1.0, 0.0);
     glVertex3f(-1.0, -1.0, 0.0);
    glColor3f(0.0, 0.0, 1.0);
     glVertex3f(1.0, -1.0, 0.0);
  glEnd();
   
    swapBuffers( dcWindow );   // put opengl stuff to screen
    result := true;
end;

procedure OpenGL_Resize(width : integer; height : integer);
begin
    if (Height = 0) then                                       
        Height := 1;                                         
    glViewport(0, 0, width, height);                     
    glMatrixMode(GL_PROJECTION);                           
    glLoadIdentity();                                       
    //gluPerspective(45.0,Width/Height,0.1,100.0);           
    glMatrixMode(GL_MODELVIEW);                             
    glLoadIdentity;                               
end;   
   

// Try, Throw, Catch mechanism. Simple proc to display given errors. //
procedure ThrowError(pcErrorMessage : pChar);
begin
    MessageBox(0, pcErrorMessage, 'Error', MB_OK);
    Halt(0);
end;


// Standard WinProc. Handles all the messages from the System. //
function GLWndProc(Window: HWnd; AMessage, WParam, LParam: Longint): Longint; stdcall; export;
begin
    GLWndProc := 0;

    case amessage of
        wm_create:
        begin
            active := true;      // if GL Window was created correctly, then set
            exit;         // active-flag to "true".
        end;

        wm_paint:
        begin
            exit;         // nothing to paint to Windows as we do all drawing with OGL
        end;
       
        wm_size:
        begin
            OpenGL_Resize(LOWORD(lParam), HIWORD(lParam));
            active := true;
            exit;
        end;
       
        wm_move:
        begin
            writeln('move window');
            exit;
        end;

        wm_keydown:
        begin
            if wParam = VK_ESCAPE then
                SendMessage(hWindow,wm_destroy,0,0);
            exit;         // check for ESC key. If pressed, then send quit message
        end;

        wm_destroy:
        begin
            active := false;   // if quit message was sent, exit the main loop by setting
            PostQuitMessage(0);   // the active-flag to "false".
            exit;
        end;

        wm_syscommand:      // system wants something..
        begin
            case (wParam) of
                SC_SCREENSAVE : begin      // ..don't start any screensavers.
                    GLWndProc := 0;
                end;

                SC_MONITORPOWER : begin   // ..and don't kill monitor power.
                    GLWndProc := 0;
                end;
            end;
        end;
    end;
    GLWndProc := DefWindowProc(Window, AMessage, WParam, LParam);   // let Windows deal with the rest of the messages.
end;


// Register the Window Class. //
function WindowRegister: Boolean;
var
    WindowClass: WndClass;
begin
    WindowClass.Style           := cs_hRedraw or cs_vRedraw;
    WindowClass.lpfnWndProc     := WndProc(@GLWndProc);      // Handle to our Windows messaging interface func.
    WindowClass.cbClsExtra      := 0;
    WindowClass.cbWndExtra      := 0;
    WindowClass.hInstance       := system.MainInstance;         // Get the Windows Instance for our app.
    WindowClass.hIcon           := LoadIcon(0, idi_Application);
    WindowClass.hCursor         := LoadCursor(0, idc_Arrow);
    WindowClass.hbrBackground   := GetStockObject(WHITE_BRUSH);
    WindowClass.lpszMenuName    := nil;
    WindowClass.lpszClassName   := 'GLWindow';         // Name the specified Window Class

    WindowRegister := RegisterClass(WindowClass) <> 0;
end;


// Create the OGL Window. //
function WindowCreate(pcApplicationName : pChar): HWnd;
var
    hWindow: HWnd;      // Handle to Window
    dmScreenSettings : DEVMODE;   // Used for Full Screen Mode
begin
    hWindow := CreateWindow('GLWindow',
              pcApplicationName,
              WS_OVERLAPPEDWINDOW or WS_CLIPCHILDREN or WS_CLIPSIBLINGS,
              cw_UseDefault,
              cw_UseDefault,
              width,
              height,
              0, 0,
              system.MainInstance,
              nil);

    if hWindow <> 0 then
    begin
        ShowWindow(hWindow, CmdShow);
        UpdateWindow(hWindow);
    end;
    WindowCreate := hWindow;
end;


// Init the Window and bind OGL to it. //
function WindowInit(hParent : HWnd): Boolean;
var
    FunctionError : integer;
    pfd : PIXELFORMATDESCRIPTOR;
    iFormat : integer;   // Pixel Format

begin
    FunctionError := 0;

    dcWindow := GetDC( hParent );   // Get Device Context

    FillChar(pfd, sizeof(pfd), 0);   // Define Pixel Format
    pfd.nSize         := sizeof(pfd);
    pfd.nVersion      := 1;
    pfd.dwFlags       := PFD_SUPPORT_OPENGL OR PFD_DRAW_TO_WINDOW OR PFD_DOUBLEBUFFER;
    pfd.iPixelType    := PFD_TYPE_RGBA;
    pfd.cColorBits    := bits;
    pfd.cDepthBits    := 32;
    pfd.iLayerType    := PFD_MAIN_PLANE;

    iFormat := ChoosePixelFormat( dcWindow, @pfd );   // Create Pixel Format

    if (iFormat = 0) then
        FunctionError := 1;

    SetPixelFormat( dcWindow, iFormat, @pfd );      // Set Pixel Format
    rcWindow := wglCreateContext( dcWindow );      // Create OpenGL Context

    if (rcWindow = 0) then
        FunctionError := 2;

    wglMakeCurrent( dcWindow, rcWindow );      // Bind OpenGL to our Window

    if FunctionError = 0 then
        WindowInit := true
    else
        WindowInit := false;
end;


// Main function to create the Window. //
function CreateOGLWindow(pcApplicationName : pChar; iApplicationWidth, iApplicationHeight, iApplicationBits : longint; bApplicationFullscreen : boolean):Boolean;
begin
    width := iApplicationWidth;
    height := iApplicationHeight;
    bits := iApplicationBits;
    fullscreen := bApplicationFullscreen;

    if not WindowRegister then begin
        ThrowError('Could not register the Application Window!');
        CreateOGLWindow := false;
        Exit;
    end;

    hWindow := WindowCreate(pcApplicationName);
    if longint(hWindow) = 0 then begin
        ThrowError('Could not create Application Window!');
        CreateOGLWindow := false;
        Exit;
    end;

    if not WindowInit(hWindow) then begin
        ThrowError('Could not initialise Application Window!');
        CreateOGLWindow := false;
        Exit;
    end;

    CreateOGLWindow := true;
end;


// Kill Application Window again. //
procedure KillOGLWindow();
begin
    wglMakeCurrent( dcWindow, 0 );   // Kill Device Context
    wglDeleteContext( rcWindow );   // Kill Render Context
    ReleaseDC( hWindow, dcWindow );   // Release Window
    DestroyWindow( hWindow );      // Kill Window itself
end;


// Main Loop. //
begin
    CreateOGLWindow('tura', 800, 600, 32, false);
    OpenGL_Init();         // init opengl stuff

    repeat            // start main proc
        if PeekMessage(@msg,0,0,0,0) = true then
        begin
            GetMessage(@msg,0,0,0);
            TranslateMessage(msg);
            DispatchMessage(msg);
        end;
        OpenGL_Render();
    until active = false;      // end main proc
   
    KillOGLWindow();      // kill window stuff
end.


Может как-то надо подкрутить в GLWndProc? :?

Код: Выделить всё
wm_paint:
        begin
            exit;        // может тут вместо выхода вызывать OpenGL_Render() ?
        end;


Добавлено спустя 35 минут 7 секунд:
Хм... добавил в ветку wm_paint вызов отрисовки OpenGL_render() стало получше, но всё равно моргает. Я так понимаю, функцию отрисовки вообще надо вызывать по таймеру... типа 60 раз в секунду?
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: FP OpenGL example почему пропадает картинка?

Сообщение zub » 03.09.2015 12:27:33

В примере нехватает ShowWindow, по крайней мере у меня без него не работает. Отрисовка организована в цикле обработки сообщений - т.е. эта заготовка работает по "игровому" принципу - расчитана на полноэкранный режим и всегда всё перерисовывает.
Чтоб избавиться от указаных проблем надо отключить заливку фона окна, добавить отрисовку в wm_paint и возможно в wm_size. (емнип в винапи были соответствующие флаги при создании окна)
Если ты не делаешь игру виндовс онли лучше воспользуйся LazOpenGLContext

Добавлено спустя 3 минуты 45 секунд:
>>но всё равно моргает
моргает потому что отрисовка выполняется вне сообщения отрисовки и заливка фона не отключена
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: FP OpenGL example почему пропадает картинка?

Сообщение xterro » 03.09.2015 13:09:04

ShowWindow там уже есть:
Код: Выделить всё
if hWindow <> 0 then
    begin
        ShowWindow(hWindow, CmdShow);
        UpdateWindow(hWindow);
    end;


В оригинале задумка была в том, чтобы использовать opengl без лазаревских компонетов, напрямую. Хочу поиграться с текстурами, в плане клепания с их помощью самодельного gui. Уж очень мне понравилась тема: https://www.linux.org.ru/gallery/screenshots/11239761 Хочу попробовать замутить нечто подобное(gui) Just For Fun :)

Чтоб избавиться от указаных проблем надо отключить заливку фона окна

Знать бы ещё как её отключить :(
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: FP OpenGL example почему пропадает картинка?

Сообщение zub » 03.09.2015 13:44:41

>>Хочу попробовать замутить нечто подобное(gui) Just For Fun
Для гуя такой способ не подойдет, запихай отрисовку в wm_paint и убери ее из цикла обработки сообщений, иначе будет постоянная нагрузка на процессор
>>Знать бы ещё как её отключить
Обработать WM_ERASEBKGND, возможно поиграть флагами окна
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: FP OpenGL example почему пропадает картинка?

Сообщение xterro » 03.09.2015 14:34:37

Обработать WM_ERASEBKGND, возможно поиграть флагами окна

О так помогло, спасибо :)

запихай отрисовку в wm_paint и убери ее из цикла обработки сообщений, иначе будет постоянная нагрузка на процессор

Сделал так:
Код: Выделить всё
wm_paint:
        begin
            OpenGL_Render();
            exit;         // nothing to paint to Windows as we do all drawing with OGL
        end;

// далее в основном цикле закоментил:
repeat            // start main proc
        if PeekMessage(@msg,0,0,0,0) = true then
        begin
            GetMessage(@msg,0,0,0);
            TranslateMessage(msg);
            DispatchMessage(msg);
        end;
        //OpenGL_Render();
until active = false;      // end main proc


Так?

Ещё момент, как думаете, стоит ли вызывать отрисовку по таймеру? Или это имеет смысл только для каких-то динамических приложений, типа игр?
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: FP OpenGL example почему пропадает картинка?

Сообщение zub » 03.09.2015 15:06:02

да, примерно както так
По таймеру нестоит, но тебе видней)) ИМХО для динамики постоянная перерисовка с замером времени между кадрами и движением объектов на соответствующие величины. Для статики - отрисовка в wm_paint.
Игрописатели подтянутся и разложат это всё по полочкам))
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: FP OpenGL example почему пропадает картинка?

Сообщение xterro » 03.09.2015 15:44:37

Понял, благодарствую :D
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33

Re: FP OpenGL example почему пропадает картинка?

Сообщение zub » 03.09.2015 17:25:59

>>ShowWindow там уже есть:
Хз что такое CmdShow, толжно быть както так
Код: Выделить всё
ShowWindow(hWindow, {CmdShow}SW_SHOW);

В виде как в первом посте у меня на семерке не работает, с SW_SHOW работает
zub
долгожитель
 
Сообщения: 2886
Зарегистрирован: 14.11.2005 23:51:26

Re: FP OpenGL example почему пропадает картинка?

Сообщение xterro » 03.09.2015 22:32:48

Хз что такое CmdShow, толжно быть както так

Хм... если честно я сам не знаю, выдрал этот пример откуда-то... Видимо какая-то переменная из модуля windows, внимание не обратил :?
xterro
постоялец
 
Сообщения: 148
Зарегистрирован: 23.02.2014 13:49:33


Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 27

Рейтинг@Mail.ru