Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: OpenGL мерцание, функция gluOrtho2D

При отображении на экран в реалтайме графика 2d, получается мерцание экрана.
Простой вывод линий в gluOrtho2D(0.0, (GLfloat)getWidth(), 0.0, (GLfloat)getHeight());
Выложил видео, что бы было понятно, хотя на видео FPS мешьше, чем в окне.


ссылка на ютуб


Добавлено через 7 минут
Полностью проблему можно увидеть в видео размером 6 мегабай, там в районе 120 фпс, главное не смотреть с сайта, там будет 30 фпс.
Ответ: Двойная буферизация используется.
PFD_DOUBLEBUFFER;
Вопрос: Уроки OpenGL - FAQ

Уроки OpenGL

Оглавление









Урок 8. Освещение (урок в разработке...)

Предисловие

Об OpenGL

OpenGL - независимый от языка программирования и платформы программный интерфейс (библиотека) для рисования двухмерной и трехмерной графики.

В отличие от WinAPI GDI, в OpenGL поддерживается прозрачность Alpha (позволяющая рисовать полупрозрачные элементы), а, также разные игровые "фичи" (текстурные и градиентные заливки, туман, и др.), и, как вы уже знаете, трехмерная графика.


Об этом FAQ

Если вы новичок в программировании, то, прежде чем взяться за это FAQ, изучите, хотя бы, пару книг по основам C++ и WinAPI... Все это, нам здесь пригодится...

В FAQ почти не будет текста, зато, будет много кода и иллюстраций.

Код - в основном, на C++ в Visual Studio, поэтому, работает, только, на Windows.
"Красноглазые" могут легко его портировать, на Linux... Им, все равно, заняться нечем...


Что нужно для OpenGL. Где скачать OpenGL. Как установить OpenGL

Прежде, чем приступить, непосредственно, к урокам, я отвечу на эти 3 вопроса, довольно часто возникающие на форумах.

Для разработки на C++ под OpenGL, нужны 3 вещи:
0) ОС семейства Windows с установленной Visual Studio или Visual C++ Express.
1) Библиотека opengl32.dll. Уже входит в Windows - лежит в system32 или SysWOW64... Если не уверены (работаете с каким-то особым, или очень старым, изданием Windows) - проверьте сами...
2) Статическая библиотека opengl32.lib. Уже входит в Visual Studio. Достаточно не забывать про #pragma comment (подробнее - см. Урок 1 и следующие уроки).
3) Заголовок gl/GL.h, содержащий объявления функций OpenGL. Уже входит в Visual Studio. Достаточно не забывать про #include.

Для того, чтобы работало ваше приложение на OpenGL, нужна только opengl32.dll - которая входит в Windows, поэтому, кроме EXEшника, ничего распространять не нужно.

Несколько иначе обстоит дело с библиотекой GLUT... Это не часть OpenGL, а сторонняя библиотека, поэтому она не входит в ОС, ее нужно скачать для разработки, и ее нужно распространять с вашей программой... Но, об этом позже, и, в первом уроке мы ее использовать не будем.


Урок 1. Рисование OpenGL в окне на WinAPI

Особенности OpenGL


Система координат.
Счет ведется от центра окна, а не, от левого верхнего угла.
Ось Y направлена вверх. Ось X - направлена вправо. Ось Z - направлена вглубь.
Единица измерения - не пиксель, а, доля (дробь от 0.0 до 0.1) отрезка от центра до верхнего края экрана (Y), до правого края экрана (X),
или до бесконечности (Z).
Так как такая система координат зависит от размера окна, то, при изменении размера окна, все графические примитивы, также, пропорционально изменяются в размере.
См. иллюстрацию "Система координат".

Формирование цвета.
Каждая из составляющих цвета (R, G, B, A) лежит в диапазоне от 0.0 до 1.0, а, не от 0 до 255.
255 = 1.0.
0 = 0.0.
128 = 0.5.

Отрисовка многоугольника.
Многоугольник, как бы, обводится по точкам. Последовательность точек - важна. От нее зависит порядок обводки.



Создадим окно на WinAPI и нарисуем в нем темно-зеленый прямоугольник с помощью OpenGL. Чтобы продемонстрировать трехмерность, реализуем поворот прямоугольника по осям X и Y на 5 градусов, при нажатии любой клавиши:

Код

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#define UNICODE
 
// WinAPI
#include <Windows.h>
#include <tchar.h>
 
// OpenGL
#pragma comment(lib, "Opengl32.lib")
#include <gl/GL.h>
 
// Глобальные константы
TCHAR *szWndClass = L"OpenGLWindow";
 
// Глобальные переменные
HWND  hWnd;
HDC   hDC;
 
HGLRC hRC;
 
int Angle = 0;
 
// Функции для создания окна Win32
ATOM RegClass(HINSTANCE hInst);
HWND CreateWnd(HINSTANCE hInst);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
 
// Функции для работы с OpenGL
void GLInit();
void GLRenderScene();
void GLShutdown();
 
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nShowCmd)
{
    // Регистрация класса окна
    if (!RegClass(hInst))
    {
        MessageBox(0, L"Не могу зарегистрировать класс окна...", 0, 0);
        return 1;
    }
 
    // Создание окна
    hWnd = CreateWnd(hInst);
    if (hWnd == NULL)
    {
        MessageBox(0, L"Не могу создать окно...", 0, 0);
        return 1;
    }
 
    // Инициализация OpenGL
    GLInit();
 
    // Главный цикл приложения
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
 
    return 0;
}
 
ATOM RegClass(HINSTANCE hInst)
{
    // Все стандартное, как и обычно, в WinAPI...
    WNDCLASS wc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hbrBackground = 0;
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    wc.hIcon = 0;
    wc.hInstance = hInst;
    wc.lpfnWndProc = WndProc;
    wc.lpszClassName = szWndClass;
    wc.lpszMenuName = 0;
    wc.style = CS_HREDRAW | CS_VREDRAW; // Окно перерисовывается при растягивании
 
    return RegisterClass(&wc);
}
 
HWND CreateWnd(HINSTANCE hInst)
{
    // Создание окна - снова, все, как обычно...
    return CreateWindowW(szWndClass, 0,
        WS_VISIBLE | WS_SYSMENU | WS_SIZEBOX | WS_MAXIMIZEBOX | WS_MINIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        0, 0, hInst, 0);
}
 
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    PAINTSTRUCT ps;
 
    switch (msg)
    {
    case WM_PAINT:
        BeginPaint(hWnd, &ps);
        GLRenderScene(); // Рендеринг (отрисовка) сцены
        EndPaint(hWnd, &ps);
        break;
    case WM_SIZE:
        // При растягивании - получение размера окна...
        RECT rect;
        GetClientRect(hWnd, &rect);
        
        // ...и изменение размера Viewport OpenGL, по размеру окна
        glViewport(0, 0, rect.right, rect.bottom);
        break;
    case WM_KEYDOWN:
        Angle += 5; // Увеличиваем угол поворота на 5 градусов
        InvalidateRect(hWnd, 0, 0); // Перерисовываем окно
        break;
    case WM_DESTROY:
        GLShutdown(); // При выходе - очистка контекта OpenGL (hRC) и WinAPI GDI (hDC)
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
        break;
    }
 
    return 0;
}
 
void GLInit()
{
    // Получение контекста WinAPI GDI
    hDC = GetDC(hWnd);
 
    // Настройка формата пикселей
    PIXELFORMATDESCRIPTOR pfd;
    memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
    pfd.nSize      = sizeof(PIXELFORMATDESCRIPTOR);
    pfd.nVersion   = 1;
    pfd.dwFlags    = PFD_DRAW_TO_WINDOW
        | PFD_SUPPORT_OPENGL // Поддержка OpenGL
        | PFD_DOUBLEBUFFER; // Двойная буферизация (чтобы изображение не мерцало)
    pfd.iPixelType = PFD_TYPE_RGBA; // Пиксели поддерживают прозрачность Alpha (поэтому, RGBA, а не RGB)
    pfd.cColorBits = 16; // Глубина цвета - 16 бит
    pfd.cDepthBits = 16;
 
    int iPixelFormat = ChoosePixelFormat(hDC, &pfd);
 
    PIXELFORMATDESCRIPTOR bestMatch_pfd;
    DescribePixelFormat(hDC, iPixelFormat, sizeof(pfd), &bestMatch_pfd);
 
    SetPixelFormat(hDC, iPixelFormat, &pfd);
 
    // Создание контекста OpenGL
    hRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRC);
 
    // Заливка фона черным:
    // R     = 0/255   = 0.0
    // G     = 0/255   = 0.0
    // B     = 0/255   = 0.0
    // Alpha = 255/255 = 1.0
    glClearColor(0.0, 0.0, 0.0, 1.0);
}
 
void GLRenderScene()
{
    // Очищаем буфер цвета и глубины
    // чтобы старый (неповернутый) прямоугольник - стирался
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glLoadIdentity();
 
    // Поворачиваем сцену на угол Angle, по осям X (1.0), Y (1.0), но не Z (0.0)
    glRotatef(Angle, 1.0, 1.0, 0.0);
 
    // Цвет прямоугольника - темно-зеленый:
    // R = 0/255   = 0
    // G = 127/255 = 0.5
    // B = 0/255   = 0
    glColor3f(0.0, 0.5, 0.0);
 
    // Рисование прямоугольника
    // высота: 1 половина высоты окна =                      1.0 ед.
    // ширина: 0.25 ширины окна = 0.5 половины ширины окна = 0.5 ед.
    glBegin(GL_POLYGON);
    glVertex2f(0, 0); // Левый-нижний угол
    glVertex2f(0, 1.0); // Левый-верхний угол
    glVertex2f(0.5, 1.0); // Правый-верхний угол
    glVertex2f(0.5, 0); // Правый-нижний угол
    glEnd();
 
    SwapBuffers(hDC);
}
 
void GLShutdown()
{
    if (hRC != NULL)
    {
        wglMakeCurrent(NULL, NULL); // Делаем NULL текущим контекстом OpenGL (восстанавливаем умолчание)
        wglDeleteContext(hRC); // Удаляем и обNULLяем наш контекст
        hRC = NULL;
    }
 
    if (hDC != NULL)
    {
        ReleaseDC(hWnd, hDC); // Удаляем и обNULLяем наш контекст WinAPI GDI
        hDC = NULL;
    }
}
Ответ: Смолевич, доброго времени суток.
У меня есть программа, которая рисует различные фигуры, различными методами. Возникла проблема при попытке сделать градиентную заливку для треугольника. Задаю красный и желтый цвета вершинам треугольника, а градиент отрисовывается из красного в черный. При этом градиентная заливка линии выполняется. Вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
// KG_2.cpp: определяет точку входа для приложения.
//
 
#include "stdafx.h"
#include <GL\gl.h>
#include <GL\GLU.h>
#include <GL\glut.h>
 
#pragma comment(lib, "OpenGL32.lib")
 
// Ссылка на поверхность рисования
HDC hDC;
// Ссылка на OpenGL через которую передаем параметр
HGLRC hGLRC;
// Ссылка на окно
HWND hWnd;
// Порядковый номер сцены
INT Scene;
 
#define MAX_LOADSTRING 100
 
// Глобальные переменные:
HINSTANCE hInst;                                // текущий экземпляр
WCHAR szTitle[MAX_LOADSTRING];                  // Текст строки заголовка
WCHAR szWindowClass[MAX_LOADSTRING];            // имя класса главного окна
 
// Отправить объявления функций, включенных в этот модуль кода:
ATOM                MyRegisterClass(HINSTANCE hInstance);
BOOL                InitInstance(HINSTANCE, int);
LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
// Функции для работы с OpenGL
void GLInit();
void GLRenderScene();
void GLShutdown();
 
INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
 
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
 
    // TODO: разместите код здесь.
    Scene = 0;
    // Инициализация глобальных строк
    LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    LoadStringW(hInstance, IDC_KG_2, szWindowClass, MAX_LOADSTRING);
    MyRegisterClass(hInstance);
 
    // Выполнить инициализацию приложения:
    if (!InitInstance (hInstance, nCmdShow))
    {
        return FALSE;
    }
 
    HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_KG_2));
 
    MSG msg;
 
    // Цикл основного сообщения:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
 
    return (int) msg.wParam;
}
 
 
 
//
//  ФУНКЦИЯ: MyRegisterClass()
//
//  НАЗНАЧЕНИЕ: регистрирует класс окна.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex;
 
    wcex.cbSize = sizeof(WNDCLASSEX);
 
    wcex.style          = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc    = WndProc;
    wcex.cbClsExtra     = 0;
    wcex.cbWndExtra     = 0;
    wcex.hInstance      = hInstance;
    wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_KG_2));
    wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName   = MAKEINTRESOURCEW(IDC_KG_2);
    wcex.lpszClassName  = szWindowClass;
    wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
 
    return RegisterClassExW(&wcex);
}
 
//
//   ФУНКЦИЯ: InitInstance(HINSTANCE, int)
//
//   НАЗНАЧЕНИЕ: сохраняет обработку экземпляра и создает главное окно.
//
//   КОММЕНТАРИИ:
//
//        В данной функции дескриптор экземпляра сохраняется в глобальной переменной, а также
//        создается и выводится на экран главное окно программы.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
   hInst = hInstance; // Сохранить дескриптор экземпляра в глобальной переменной
   //CW_USEDEFAULT
   hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
      0, 0, 400, 400, nullptr, nullptr, hInstance, nullptr);
 
   if (!hWnd)
   {
      return FALSE;
   }
 
   GLInit();
   ShowWindow(hWnd, nCmdShow);
   UpdateWindow(hWnd);
 
   return TRUE;
}
 
//
//  ФУНКЦИЯ: WndProc(HWND, UINT, WPARAM, LPARAM)
//
//  НАЗНАЧЕНИЕ:  обрабатывает сообщения в главном окне.
//
//  WM_COMMAND — обработать меню приложения
//  WM_PAINT — отрисовать главное окно
//  WM_DESTROY — отправить сообщение о выходе и вернуться
//  WM_KEYDOWN — обработать нажатие клавиши
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
        {
            int wmId = LOWORD(wParam);
            // Разобрать выбор в меню:
            switch (wmId)
            {
            case IDM_ABOUT:
                DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
                break;
            case IDM_EXIT:
                DestroyWindow(hWnd);
                break;
            default:
                return DefWindowProc(hWnd, message, wParam, lParam);
            }
        }
        break;
    case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            // TODO: Добавьте сюда любой код прорисовки, использующий HDC...
            GLRenderScene(); // Рендеринг (отрисовка) сцены
            EndPaint(hWnd, &ps);
        }
        break;
    case WM_KEYDOWN:
        {
            switch (wParam)
            {
            case VK_LEFT:
                if (Scene > 0)
                {
                    Scene -= 1;
                    InvalidateRect(hWnd, 0, 0); // Перерисовываем окно
                }
                break;
            case VK_RIGHT:
                if (Scene < 2)
                {
                    Scene += 1;
                    InvalidateRect(hWnd, 0, 0); // Перерисовываем окно
                }
                break;
            default:
                break;
            }
        }
        break;
    case WM_DESTROY:
        GLShutdown();
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}
 
// Инициализация OpenGL
void GLInit()
{
    // Получаем ссылку на поверхность
    hDC = GetDC(hWnd);
 
    PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_SUPPORT_OPENGL |
        PFD_DRAW_TO_WINDOW |
        PFD_DOUBLEBUFFER,
        PFD_TYPE_RGBA,
        32,
        0, 0, 0, 0, 0, 0,
        0,
        0,
        0,
        0, 0, 0, 0,
        16,
        0,
        0,
        PFD_MAIN_PLANE,
        0,
        0, 0, 0,
    };
 
    // Задаем формат пикселей
    int pixelFormat = ChoosePixelFormat(hDC, &pfd);
    // Задаем параметры точек
    SetPixelFormat(hDC, pixelFormat, &pfd);
    // сообщаем OpenGL где будем рисовать
    hGLRC = wglCreateContext(hDC);
    // Создаем контекст рисования
    wglMakeCurrent(hDC, hGLRC);
    // Заливка фона черным:
    // R     = 0/255   = 0.0
    // G     = 0/255   = 0.0
    // B     = 0/255   = 0.0
    // Alpha = 255/255 = 1.0
    glClearColor(0.0, 0.0, 0.0, 1.0);
}
 
// Отрисовка сцены
void GLRenderScene()
{
    // Очищаем буфер цвета и глубины
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glLoadIdentity();
    glShadeModel(GL_SMOOTH);
    glEnable(GL_LINE_SMOOTH);
    glEnable(GL_LINE_STIPPLE);
    glEnable(GL_COLOR_MATERIAL);
    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_BLEND);
    // Глобальные переменные
    double angle, R; // угол и радиус
    GLdouble x, y; // координаты точки
    int n; // количество углов
 
    switch (Scene)
    {
    case 0:
        /* Отрисовка первой сцены */
        glPointSize(2);  //размер точки
        glBegin(GL_POINTS);
        glColor3d(1, 0, 0);
        glVertex3d(0, 0, 0);    // первая точка
        glColor3d(0, 1, 0);
        glVertex3d(1, 0, 0);    // вторая точка
        glColor3d(0, 0, 1);
        glVertex3d(0, 1, 0);    // третья точка
        glEnd();
        //Рисуем многоугольники
        glColor3d(0, 1, 0);
        glLineWidth(2);
        //glLineStipple(1, 0x0101);
        // Рисуем многоугольник №1
        glBegin(GL_LINE_LOOP);
        angle = 0;
        x = -0.5;
        y = 0.5;
        n = 12; // количество углов
        R = 0.1; // радиус
        for (int i = 0; i < n; i++)
        {
            x = x + R*cos(angle*M_PI / 180); //Запоминаем каждую следующую координату x
            y = y + R*sin(angle*M_PI / 180); //Запоминаем каждую следующую координату y
            angle = angle + 360 / n; //Увеличиваем угол на величину угла правильного многоугольника
            glVertex2d(x, y);
        }
        glEnd();
        // Рисуем многоугольник №2
        glColor3d(0, 1, 1);
        glBegin(GL_POLYGON);
        angle = 0;
        x = 0.5;
        y = 0.5;
        n = 3; // количество углов
        R = 0.2; // радиус
        for (int i = 0; i < n; i++)
        {
            x = x + R*cos(angle*M_PI / 180); //Запоминаем каждую следующую координату x
            y = y + R*sin(angle*M_PI / 180); //Запоминаем каждую следующую координату y
            angle = angle + 360 / n; //Увеличиваем угол на величину угла правильного многоугольника
            glVertex2d(x, y);
        }
        glEnd();
        // Рисуем ломаную
        glColor3d(1, 1, 0);
        glBegin(GL_LINE_STRIP);
        glVertex2d(0.1, -0.4);
        glVertex2d(0.5, -0.1);
        glVertex2d(0.8, -0.3);
        glVertex2d(0.3, -0.5);
        glVertex2d(0.4, -0.8);
        glVertex2d(1, -0.3);
        glEnd();
        // Рисуем треугольники
        glColor3d(1, 0, 0);
        glBegin(GL_LINE_LOOP);
        glVertex2d(-0.2, -0.1);
        glVertex2d(-0.5, -0.4);
        glVertex2d(-0.1, -0.7);
        glVertex2d(-0.5, -0.8);
        glVertex2d(-0.7, -0.6);
        glVertex2d(-0.6, -0.5);
        glColor3d(1, 1, 0);
        glVertex2d(-0.8, -0.2);
        glEnd();
        break;
    case 1:
        // Рисуем треугольники
        glBegin(GL_TRIANGLES);
        // 1
        glColor3d(1, 0, 0);
        glVertex2d(-0.2, -0.1);
        glVertex2d(-0.6, -0.5);
        glVertex2d(-0.8, -0.2);
        // 2
        glColor3b(0, 0, 1);
        glVertex2d(-0.5, -0.4);
        glColor3d(1, 0, 0);
        glVertex2d(-0.1, -0.7);
        glVertex2d(-0.5, -0.8);
        // 3
        glColor3d(1, 0, 0);
        glVertex2d(-0.5, -0.8);
        glColor3b(1, 1, 0);
        glVertex2d(-0.7, -0.6);
        glColor3b(1, 1, 1);
        glVertex2d(-0.5, -0.4);
        glEnd();
        //
        break;
    case 2:
        //
        break;
    default:
        break;
    }
 
    // Двойная буфферизация
    SwapBuffers(hDC);
}
 
// При выходе - очистка контекта OpenGL(hRC) и WinAPI GDI(hDC)
void GLShutdown()
{
    if (hGLRC != NULL)
    {
        wglMakeCurrent(NULL, NULL); // Делаем NULL текущим контекстом OpenGL (восстанавливаем умолчание)
        wglDeleteContext(hGLRC); // Удаляем и обNULLяем наш контекст
        hGLRC = NULL;
    }
 
    if (hDC != NULL)
    {
        ReleaseDC(hWnd, hDC); // Удаляем и обNULLяем наш контекст WinAPI GDI
        hDC = NULL;
    }
}
 
// Обработчик сообщений для окна "О программе".
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
    UNREFERENCED_PARAMETER(lParam);
    switch (message)
    {
    case WM_INITDIALOG:
        return (INT_PTR)TRUE;
 
    case WM_COMMAND:
        if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
        {
            EndDialog(hDlg, LOWORD(wParam));
            return (INT_PTR)TRUE;
        }
        break;
    }
    return (INT_PTR)FALSE;
}
Вопрос: OpenGL,D3D. Кроссплатформенность

Запутался в такой вещи как кросс-платформенность. Гуглил около часа, но так допереть и не смог.
Скажем пишем мы 2 похожие программы на C++. Одну с использованием Direct3D, другую с использованием OpenGL.
После сборки программы с использованием Direct3D - получаем exe файлик, где при запуске динамически подгружаются из Direct3D.dll функции, использующие WinAPI.
При сборке программы с использованием OpenGL происходит всё тоже самое. Отличие только в том, что разработчик dll-ки не Microsoft, а другая компания, и называется соответственно как-то по другому OpenGL.dll скажем.

А кросс-платформенность OpenGL заключается в том, что компания-разработчик библиотеки OpenGL может сделать не только dll-ку, но и .so? Если да, то почему этого не может сделать Microsoft?

В общем запутался...
Ответ: с появлением VBO весь остальной функционал все равно становится useless. Вернее это причина появления VBO. И причины чисто железячные. Трансфер по PCI-E - 4ГБ/сек, по шине видеокарты - 148. т.е. то что без VBO становится useless. А поскольку в HAL уже реализована заброска буферов в железо и манипуляция ими, то делать дубликат никому не надо, мало того очень проблемно, учитывая Exclusive и Shared Mode использования железа. А вот SAL - Software Abstraction Layer на него можно лепить какой угодно. Хоть Direct3D хоть GL хоть вообще все что угодно, но юзает оно буфера из HAL (IDirect3DResource).

Добавлено через 8 минут
а вернее класса который реализовывает этот интерфейс. Вообще доступ к функциям железа для недрайверов под виндой возможен только через HAL DirectX, хотя SAL (интерфейсы) могут быть и другие. К примеру IAudioClient и IDirectXSound оборачивают один и тот же класс HAL. Но весь HAL - это системная часть DirectX. Почему DirectX так и назван. Переводится - прямой доступ к компоненту X (любому) компьютера, т.е. фактически в обход виртуализации и WinAPI.

Добавлено через 59 минут
Сообщение от kuson
весь функционал OpenGL должен быть реализован сторонними разработчиками поверх этого доступа
А что значит сторонними если в OpenGL входит в Windows отродясь? Суть кросс-платформенности OpenGL в том что каждый из разработчиков осей включает один и тот же набор функций API OpenGL в свою ось. Это же кстати и есть слабым моментом OpenGL - ограничение набора входящих в состав функций для обеспечения кросс-платформенности. А при разработке Direct3D никакими стандартами не связаны. Для примеру - W-Buffer быстрее и качественнее Z-Buffer - пожалуйста, раздельная индексация вертексов/нормалей и всех остальных буферов удобнее чем общая - тоже пожалуйста.
Вопрос: OpenGL 3.3, инициализированный WINAPI, вылетает

Всем привет.
Изучаю OpenGL v3.3(больше видяха не держит ATI Mobility Radeon HD 4300).
Уже попробовал на GLEW.
Теперь хочется на чистом WINAPI и OpenGL.
Собственно, вот код
main.cpp
Код C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
#include <windows.h>
 
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
 
#include <GL/gl.h>
#include <GL/glext4.h>
#include <GL/wglext.h>
 
#include "include/Window.h"
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
 
//Для поддержания работы OpenGL
HDC hDC;
HGLRC hRC;
 
//Секция для Объявления всех запрашиваемых процедур OpenGL
void (*glGenBuffers)(GLsizei n, GLuint* buffers);
void (*glDeleteBuffers)(GLsizei n, GLuint* buffers);
void (*glBindBuffer)(GLenum target, GLuint buffer);
void (*glGenVertexArrays)(GLsizei n, GLuint* arrays);
void (*glBindVertexArray)(GLuint array);
void (*glBufferData)(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
void (*glEnableVertexAttribArray)(GLuint index);
void (*glDisableVertexAttribArray)(GLuint index);
void (*glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid * pointer);
 
void EnableOpenGL(HWND hwnd);
void DisableOpenGL(HWND);
void InitGLAPI();
void Init();
void Render();
 
//Отладка
void check(void* fn)
{
    if(fn)
    {
        cout << "func get success, addr is "<<fn<<endl;
    }
    else
    {
        cout << "failed to load func!" <<endl;
    }
}
//Данные
static const GLfloat g_vertex_buffer_data[] = {
   -1.0f, -1.0f, 0.0f,
   1.0f, -1.0f, 0.0f,
   0.0f,  1.0f, 0.0f,
};
GLuint VertexArrayID;
GLuint vertexbuffer;
 
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int ShowMode)
{
    WIN_RegWin(hInst, "OGL");
    WIN_CreateWin(hInst, "OGL", "OpenGL 3.3", 800, 600);
    MSG Msg;
    bool Quit = false;
    while(Quit == false)
    {
        if(PeekMessage(&Msg, 0,0,0, PM_REMOVE))
        {
            if(Msg.message == WM_QUIT)Quit = true;
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
        else
        {
            Render();
        }
    }
    return 0;
}
 
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
    case WM_CREATE:
        EnableOpenGL(hwnd);
        break;
    case WM_DESTROY:
        DisableOpenGL(hwnd);
        PostQuitMessage(0);
        break;
    default:
        return (DefWindowProc(hwnd, msg, wParam, lParam));
    }
}
 
void Init()
{
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);
 
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW);
 
    glClearColor(0,0,0,1);
}
 
void Render()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glVertexAttribPointer(
       0,                  // Атрибут 0. Подробнее об этом будет рассказано в части, посвященной шейдерам.
       3,                  // Размер
       GL_FLOAT,           // Тип
       GL_FALSE,           // Указывает, что значения не нормализованы
       0,                  // Шаг
       (void*)0            // Смещение массива в буфере
    );
    // Вывести треугольник!
    glDrawArrays(GL_TRIANGLES, 0, 3); // Начиная с вершины 0, всего 3 вершины -> один треугольник
    glDisableVertexAttribArray(0);
    cout << glGetError() <<endl;
    SwapBuffers(hDC);
    cout <<GetLastError()<<endl;
}
 
void EnableOpenGL(HWND hwnd)
{
    cout << "Preparing to init OpenGL Compatible..." <<endl;
    hDC = GetDC(hwnd);
    static PIXELFORMATDESCRIPTOR pfd;
    ZeroMemory(&pfd, sizeof(pfd));
    pfd.nSize = sizeof(pfd);
    pfd.cColorBits = 32;
    pfd.cDepthBits = 24;
    pfd.nVersion = 1;
    pfd.dwFlags = PFD_DRAW_TO_WINDOW|PFD_SUPPORT_OPENGL|PFD_DOUBLEBUFFER;
    pfd.iPixelType = PFD_TYPE_RGBA;
 
    int PixelFormat = ChoosePixelFormat(hDC, &pfd);
    SetPixelFormat(hDC, PixelFormat, &pfd);
    HGLRC hRCTemp = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hRCTemp);
    int mj, mn;
    glGetIntegerv(GL_MAJOR_VERSION, &mj);
    glGetIntegerv(GL_MINOR_VERSION, &mn);
    cout << "OpenGL Compatible version is "<<mj<<"."<<mn<<endl;
 
    cout << "Preparing to init OpenGL Core..."<<endl;
    HGLRC (*wglCreateContextAttribsARB)(HDC , HGLRC , const int* );
    wglCreateContextAttribsARB = (HGLRC(*)(HDC , HGLRC , const int* ))wglGetProcAddress("wglCreateContextAttribsARB");
    if(!wglCreateContextAttribsARB)
    {
        cout << "Failed to get wglCreateContextAttribsARB!" <<endl;
    }
    else
    {
        cout << "Success to get wglCreateContextAttribsARB. Addr is " <<(void*)wglCreateContextAttribsARB<<endl;
        wglMakeCurrent(hDC, NULL);
        wglDeleteContext(hRCTemp);
    }
 
 
    int attribs[] =
    {
            WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
            WGL_CONTEXT_MINOR_VERSION_ARB, 3,
            WGL_CONTEXT_FLAGS_ARB,  WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
            WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
            0
    };
    hRC = wglCreateContextAttribsARB(hDC, 0, attribs);
    if(!hRC)
    {
        cout << "Failed to create Core context!" <<endl;
    }
    else
    {
        glGetIntegerv(GL_MAJOR_VERSION, &mj);
        glGetIntegerv(GL_MINOR_VERSION, &mn);
        cout << "Success to create Core context! Version is "<<mj<<"."<<mn<<endl;
        wglMakeCurrent(hDC, hRC);
    }
    InitGLAPI();
    Init();
}
 
void InitGLAPI()
{
    glGenBuffers = (void(*)(GLsizei,GLuint*))wglGetProcAddress("glGenBuffers");
    check((void*)glGenBuffers);
    glDeleteBuffers = (void(*)(GLsizei,GLuint*))wglGetProcAddress("glDeleteBuffers");
    check((void*)glDeleteBuffers);
    glBindBuffer = (void(*)(GLenum,GLuint))wglGetProcAddress("glBindBuffer");
    check((void*)glBindBuffer);
    glGenVertexArrays = (void(*)(GLsizei,GLuint*))wglGetProcAddress("glGenVertexArrays");
    check((void*)glGenVertexArrays);
    glBindVertexArray = (void(*)(GLuint array))wglGetProcAddress("glBindVertexArray");
    check((void*)glBindVertexArray);
    glBufferData = (void(*)(GLenum , GLsizeiptr , const GLvoid* , GLenum ))wglGetProcAddress("glBufferData");
    check((void*)glBufferData);
    glEnableVertexAttribArray =(void(*)(GLuint index))wglGetProcAddress("glEnableVertexAttribArray");
    check((void*)glEnableVertexAttribArray);
    glDisableVertexAttribArray = (void(*)(GLuint index))wglGetProcAddress("glDisableVertexAttribArray");
    check((void*)glDisableVertexAttribArray);
    glVertexAttribPointer = (void(*)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer))wglGetProcAddress("glVertexAttribPointer");
    check((void*)glVertexAttribPointer);
}
 
void DisableOpenGL(HWND hwnd)
{
    wglMakeCurrent(hDC, NULL);
    wglDeleteContext(hRC);
    ReleaseDC(hwnd, hDC);
}
include/Window.h
Код C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef WINDOW_H_INCLUDED
#define WINDOW_H_INCLUDED
 
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
 
extern LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void WIN_RegWin(HINSTANCE hInst, const char* clName);
HWND WIN_CreateWin(HINSTANCE hInst, const char* clName, const char* Title, int width, int height);
 
#endif // WINDOW_H_INCLUDED
src/Window.cpp
Код C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "../include/Window.h"
 
void WIN_RegWin(HINSTANCE hInst, const char* clName)
{
    WNDCLASS wc;
    ZeroMemory(&wc, sizeof(wc));
    wc.style = CS_HREDRAW|CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInst;
    wc.hbrBackground = CreateSolidBrush(RGB(255,255,255));
    wc.hIcon = LoadIcon(0, IDI_APPLICATION);
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    wc.lpszClassName = clName;
 
    if(!RegisterClass(&wc))
    {
        cout << "Failed to Register WC!" <<endl;
    }
    else
    {
        cout << "WC registered!" <<endl;
    }
}
 
HWND WIN_CreateWin(HINSTANCE hInst, const char* clName, const char* Title, int width, int height)
{
    RECT adj={0,0,width,height};
    AdjustWindowRect(&adj, WS_OVERLAPPEDWINDOW, FALSE);
 
    HWND hwnd = CreateWindow(clName, Title, WS_OVERLAPPEDWINDOW, 200,0, adj.right, adj.bottom, 0,0,hInst,0);
    ShowWindow(hwnd, SW_SHOWNORMAL);
    cout << "Window created!" <<endl;
    return hwnd;
}
Все это дело успешно компилируется, при запуске рисует белый треугольник(как и должно), в консоли ошибок не выдает, адреса всех GLAPI функций получаются успешно, но после одного цикла отрисовки приложение вылетает: "прекращена работа программы", предположительно после glDrawArrays(GL_TRIANGLES, 0, 3); или glDisableVertexAttribArray(0);, но вызов glGetError() после обеих функций возвращает 0.
Хотелось бы знать почему так и что с этим можно сделать?
IDE: CodeBlocks 13.12 с идущим в комплекте компилятором MinGW.
glext4.h - просто новая версия glext.h
ОС: Win7 64 bit SP1
Ответ: Вот такое попробуйте в цикле.
Код C++
1
2
3
4
5
6
    GLenum err;
    char input[32];
    while ((err = glGetError()) != GL_NO_ERROR) {
           sprintf(input, "Error OpenGL: " "%d"  , err);
           MessageBox(NULL, input, NULL, NULL);
       };
Используйте исключительно GLEW, стандартный возможно не знает ряд функций.
Вопрос: OpenGL движение фигуры в окне

Здравствуйте, форумчане. Есть проблема. Есть код, который реализует вращение фигуры по осям. Встала проблема, как сделать движение в окне ( так сказать в плоскости ). Причем движение должно осуществляться посредством нажатия на клавиши ( например, стрелка влево/вправо - должен осуществляться поворот соответственно влево/вправо ). Так сказать нужно сделать так, чтобы фигура двигалась по принципу движения машинок в GTA 2. Пишу на Qt. Вот код:
*.pro
Код C++ (QT)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#-------------------------------------------------
#
# Project created by QtCreator 2015-06-15T20:59:05
#
#-------------------------------------------------
 
QT       += core gui
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
TARGET = opengl-ka
TEMPLATE = app
 
 
SOURCES += main.cpp\
        widget.cpp
 
HEADERS  += widget.h
 
FORMS    += widget.ui
 
QT += opengl
widget.h
Код C++ (QT)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#ifndef WIDGET_H
#define WIDGET_H
 
#include <QtGui>
#include <QtOpenGL/QGLWidget>
#include <QTimer>
#include <GL/gl.h>
 
namespace Ui {
class Widget;
}
 
class Widget : public QGLWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = 0);
 
protected:
    void initializeGL();
    void resizeGL(int nWidth, int nHeight);
    void paintGL();
    void scene();
    void rotate();
 
    double angle;
    QTimer *timer;
 
public slots:
    void tiktak();
};
 
#endif // WIDGET_H
widget.cpp
Код C++ (QT)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent)
    : QGLWidget(parent)
{
    angle = 0;
    timer = new QTimer;
    QObject::connect(timer,SIGNAL(timeout()),SLOT(tiktak()));
    timer->start(10);
    setWindowTitle("Okoshko");
    resize(700,700);
}
 
void Widget::initializeGL()
{
    //Задаем цвет фона в OpenGL окне
    qglClearColor(Qt::black);
 
    //Задаем режим обработки полигонов - переднюю и заднюю часть, полигоны полностью закрашеные (а можно просто рамку отображать)
    glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}
 
void Widget::resizeGL(int nWidth, int nHeight)
{
    //Установляем точку обзора. Последние два параметры одинаковы - чтобы не нарушать пропорции у широких экранов (можете поекспериментировать)
    glViewport(0, 0, nWidth, nHeight);
 
    //Установляем режим матрицы
    glMatrixMode(GL_PROJECTION);
 
    //Загружаем матрицу
    glLoadIdentity();
}
 
void Widget::paintGL()
{
    //Очищаем экран
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    //Задаем режим матрицы
    glMatrixMode(GL_PROJECTION);
 
    //Загружаем матрицу
    glLoadIdentity();
 
    //Здесь рисуем - для удобства в отдельной функции
    scene();
    //выводим на екран
    swapBuffers();
}
 
 
void Widget::scene()
{
 
    //Задаем цвет изображения
    qglColor(Qt::green);
 
    //Начинаем отрисовку, аргумент означает отрисовку прямоугольника. Каждый вызов glVertex3f задает одну вершину прямоугольника
    glBegin(GL_QUADS);
    glVertex3f (0.1, 0.1, 0.1);
    glVertex3f (-0.1, 0.1, 0.1);
    glVertex3f (-0.1, -0.1, 0.1);
    glVertex3f (0.1, -0.1, 0.1);
    glEnd();
}
 
void Widget::rotate()
{
    //При каждом вызове функции прибавляем к углу поворота один градус
    angle += 1;
 
    //Проверяем переполнение (360 градусов)
    (angle > 360)? angle = 0: 0;
 
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
 
    //Очищаем экран
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 
    glRotated(angle,0,0,1);     //Делаем поворот системы
    paintGL();    //Вызываем функцию отрисовки для
 
}
 
void Widget::tiktak()
{
    rotate();
}
main.cpp
Код C++ (QT)
1
2
3
4
5
6
7
8
9
10
11
#include "widget.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
 
    return a.exec();
}
Прошу помощи.
Ответ: В общем, разобрался. Скину код, может кому пригодится)
*.pro
Код C++ (QT)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#-------------------------------------------------
#
# Project created by QtCreator 2015-06-29T09:23:49
#
#-------------------------------------------------
 
QT       += core gui
 
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 
TARGET = one
TEMPLATE = app
 
 
SOURCES += main.cpp\
        widget.cpp
 
HEADERS  += widget.h
 
FORMS    += widget.ui
 
QT += opengl
*.h
Код C++ (QT)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#ifndef WIDGET_H
#define WIDGET_H
 
#include <QtGui>
#include <QtOpenGL/QGLWidget>
#include <QMatrix4x4>
 
namespace Ui {
class Widget;
}
 
class Widget : public QGLWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
 
protected:
    void initializeGL();
    void resizeGL(int nWidth, int nHeight);
    void paintGL();
 
    void translate_up();
    void translate_down();
    void translate_left();
    void translate_right();
    void keyPressEvent(QKeyEvent* event);
 
private:
    QMatrix4x4 current_matrix;
    double x1,x2,x3,x4,y1,y2,y3,y4,z1,z2,z3,z4;
    float angle;
 
private:
    Ui::Widget *ui;
};
 
#endif // WIDGET_H
*.cpp
Код C++ (QT)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "widget.h"
#include "ui_widget.h"
 
Widget::Widget(QWidget *parent)
    : QGLWidget(parent)
    , current_matrix(1.0, 0.0, 0.0, 0.0,
                     0.0, 1.0, 0.0, 0.0,
                     0.0, 0.0, 1.0, 0.0,
                     0.0, 0.0, 0.0, 1.0)
{
    angle = 6.0f;
}
 
void Widget::initializeGL()
{
   qglClearColor(Qt::black);
   glEnable(GL_DEPTH_TEST);
   glShadeModel(GL_FLAT);
   glEnable(GL_CULL_FACE);
   glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
}
 
void Widget::resizeGL(int n1, int n2)
{
    glViewport(1, 1, n1, n2);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
}
 
void Widget::paintGL() // рисование
{
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // очистка буфера изображения и глубины
 
   glMatrixMode(GL_MAX_3D_TEXTURE_SIZE); // устанавливает положение и ориентацию матрице моделирования
 
   glLoadMatrixf(current_matrix.data());
 
   QColor halfGreen(0, 128, 0, 255);
   qglColor(halfGreen);
   glBegin(GL_QUADS);
       glVertex3f(0.1, 0.1, 0.1);
       glVertex3f(-0.1, 0.1, 0.1);
       glVertex3f(-0.1, -0.1, 0.1);
       glVertex3f(0.1, -0.1, 0.1);
   glEnd();
 
}
 
void Widget::keyPressEvent(QKeyEvent* event) // нажатие определенной клавиши
{
   switch (event->key())
   {
 
      case Qt::Key_Down:
         translate_down(); // транслировать сцену вниз
      break;
 
      case Qt::Key_Up:
         translate_up();   // транслировать сцену вверх
      break;
 
      case Qt::Key_Left:
         translate_left(); // транслировать сцену влево
      break;
 
      case Qt::Key_Right:
         translate_right();   // транслировать сцену вправо
      break;
 
      case Qt::Key_Escape: // клавиша "эскейп"
        this->close();    // завершает приложение
      break;
 
   }
   updateGL(); // обновление изображения
}
 
void Widget::translate_down() // транслировать сцену вниз
{
    current_matrix.translate(0.0, -0.1, 0.0);
    updateGL();
}
 
void Widget::translate_up() // транслировать сцену вниз
{
    current_matrix.translate(0.0, 0.1, 0.0);
    updateGL();
}
 
void Widget::translate_right() // транслировать сцену вниз
{
    current_matrix.rotate(angle, 0.0, 0.0, -1.0);
    updateGL();
}
 
void Widget::translate_left() // транслировать сцену вниз
{
    current_matrix.rotate(angle, 0.0, 0.0, 1.0);
    updateGL();
}
main.cpp
Код C++ (QT)
1
2
3
4
5
6
7
8
9
10
11
12
13
#include "widget.h"
#include <QApplication>
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.setWindowTitle("BomBom");
    w.resize(700,700);
    w.show();
 
    return a.exec();
}
Вопрос: GlOrtho() и OpenGL 3+

Такой вопрос, используется ли сейчас функция glOrtho() в версиях OpenGL выше 3.2 ?

Если нет то какие функции взяли на себя работу функции glOrtho() ?

P.s.
На сайте OpenGL, в справочнике (), функция glOrtho() вообще отсутствует.
Ответ:
Сообщение от koker007
OpenGL выше 3.2
GL больше таким не занимается. Нужны сторонние библиотеки. Например glm

glm.g-truc.net/
Вопрос: Литература по OpenGL

Посоветуйте, пожалуйста, хорошую литературу по OpenGL. Сейчас читаю OpenGL Суперкнига, но, к примеру, есть функция отрисовки тора/сферы, а вот как она реализуется - нету (да, я могу посмотреть код, но мне нужен сам принцип построения, а не готовый код).
Ответ:
Цитата Сообщение от Мизантроп_Лол Посмотреть сообщение
на первом курсе я лабы по паскалю делал)
Аналогично, во втором семестре... ох и было матов по поводу паскаля после лаб и курсака по C++ в первом. И табуляция с графиком была и там и там. Ну просто функции табулировали наверное вообще все. Это в лабах по всем языкам есть. С этого кстати информатика вообще начинается. И машина Бэбиджа, и машина Паскаля для этих целей задумывалась.

Добавлено через 2 минуты
Цитата Сообщение от Мизантроп_Лол Посмотреть сообщение
Движка.
Движок он обычно конвейер пользует, или свой софтверный имеет. Примеры конвейеров Direct3D и OpenGL
Вопрос: Сделать окно OpenGL в MFC приложении visual studio 2013

Добрый день друзья!

Столкнулся с такой проблемой, что нужно реализовать OpenGL окно в одностраничном приложении MFC с статической библиотекой на visual studio 2013.

Простым зыком, в окне приложения должно отображаться окно OpenGL + пару кнопок управления.

Часть с OpenGL я уже реализовал в консольном приложении, теперь нужно перенести это все в приложение MFC, но не как не врубаюсь, да и инфы мало в инете (если есть то не актуальная).

Помогите пожалуйста, уже неделю бьюсь над этим.
Ответ: rmurad93, я в MFC не работал, но так или иначе думаю он позволяет добраться либо до оконной процедуры либо до обработчика сообщения WM_PAINT - в них (кроме прочих мест) вам нужно будет вызывать функции рисования. естественно рисование будет идти если вы скажете OpenGL рисовать в окно. что то вроде
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    HWND hwnd = хэндл окна в котором я хочу рисовать;
    HDC hdc = GetDC(hwnd);
    set_dc_pixel_format();
    HGLRC hglrc = wglCreateContext(hdc);
    wglMakeCurrent(hdc, hglrc);
    set_gl_params();
...
//функции которые тут используются могут выглядеть например так
void set_dc_pixel_format(void)
{
    PIXELFORMATDESCRIPTOR pfd =
    {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,
        PFD_DRAW_TO_WINDOW |
        PFD_SUPPORT_OPENGL |
        PFD_DOUBLEBUFFER |
        PFD_TYPE_RGBA,
        32,
        0, 0, 0, 0, 0, 0,
        0, 0,
        0, 0, 0, 0, 0,
        32,
        0,
        0,
        0,
        0,
        0, 0, 0
    };
    int pixel_format = ChoosePixelFormat(hdc, &pfd);
    SetPixelFormat(hdc, pixel_format, &pfd);
}
void set_gl_params(void)
{
    glEnable(GL_DEPTH_TEST);
 
    glClearDepth(NORMAL_DEPTH);
 
    glPointSize(10);
    glLineWidth(1);
 
    //что-то нужное только вам
}
вообще без вашего минимального кода это все просто обмен мнениями
Вопрос: OpenGL c++ Вращение нескольких фигур

Здравствуйте,недавно начала изучать OpenGL смотрел уроки на Ютюбе.
Вот функция рисования display ,
Snow - рисует разные звездочки в разных местах (функция представляет из себя 10 точек).
Так же есть таймер, который вызывает функцию дисплей.
Проблема в том, что вращается экран, и получается,что вращаются не сами звездочки, а экран вращается по кругу, а мне нужно, чтобы экран оставался на месте, и каждая звездочка крутилась отдельно. Могли бы подсказать пожалуйста, как быть.
Вектор хранит разные рандомные координаты этих звездочек.
Код C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void display()
{
    glClear(GL_COLOR_BUFFER_BIT);
    glRotatef(1, 0, 0, 1);
    glBegin(GL_LINES);
    for (vector<Snowflake>::iterator i = snowList.begin(); i != snowList.end(); i++)
    {
        snow(i->x,i->y);
        
    }
    glEnd();
    glutSwapBuffers();
 
}
Ответ: SatanaXIII, да показывать то нечего. в мейне, все стандартно, функцию дисплей я написал.
а вот snow
Код C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void snow(float x, float y)
{
    glVertex2f(x, y);
    glVertex2f(x, y+2.3);
    glVertex2f(x, y);
    glVertex2f(x+2.0, y+2.0);
    glVertex2f(x, y);
    glVertex2f(x+2.3, y);
    glVertex2f(x, y);
    glVertex2f(x+2.0,y -2.0);
    glVertex2f(x, y);
    glVertex2f(x, y-2.3);
    glVertex2f(x, y);
    glVertex2f(x-2.0, y-2.0);
    glVertex2f(x, y);
    glVertex2f(x-2.3, y);
    glVertex2f(x, y);
    glVertex2f(x-2.0, y+2.0);
    
}
Вопрос: Выбор оптимальной версии OpenGL

Вопрос в следующем: какими должны быть адекватные системные требования для несложной 2D-игры в 2016 году? Есть мысль, что будет некорректно создавать проект уровня Flappy Bird на OpenGL 4.x из-за несовместимости многих видеокарт с этой версией. Минимальная версия OpenGL на мой взгляд 2.0, поскольку с одной стороны охватывает железо старых поколений, с другой стороны дает возможность использовать шейдеры GLSL. Пост-обработка с использованием фреймбуфера накручивается расширениями. Но меня не устраивает ограничение, связанное с функцией glTexImage2D. Не все видеокарты уровня OpenGL 2.0 позволяют создавать в памяти текстуру выше 1024px*1024px. Так же требуется больше усилий по оптимизации под такое железо. Буду рад любым советам. Так же было бы неплохо получить какие-нибудь статистические данные по этому вопросу.
Ответ:
Сообщение от 8Observer8
У меня такая ситуация, что я собираю (в exe) игры на современном ноуте на ОС Win7.
Не имеет значения на чём собирать.
Для движка важна конфигурация машины, на которой он запускается.
Сообщение от 8Observer8
Получается, что движок собирает exe таким образом, что при запуске exe приложение само выберет, что ему использовать: OpenGL 2.0 или OpenGL 4.x?
В exe заключён движок.
Он-то и собирает свою конфигурацию динамически при запуске из имеющихся модулей.