Форум программистов, компьютерный форум, киберфорум
Наши страницы
OpenGL
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.62/101: Рейтинг темы: голосов - 101, средняя оценка - 4.62
Смолевич
94 / 53 / 5
Регистрация: 19.07.2014
Сообщений: 416
#1

Уроки OpenGL - FAQ

26.03.2015, 04:30. Просмотров 18412. Ответов 12
Метки нет (Все метки)

Уроки OpenGL

Оглавление

Предисловие
Урок 1. Рисование OpenGL в окне на WinAPI
Урок 2. GLUT vs WinAPI. Будь проще...
Урок 3. Круг, окружность, эллипс. Рисование композиций из нескольких разных фигур
Урок 4. Точка, линия, ломаная линия, кривая, замкнутая кривая. Толщина линии
Урок 5. Рисование первой 3D-фигуры. Параллелепипед
Урок 6. Градиентная заливка. Полноэкранный режим. Клавиша Esc
Урок 7. Текстурная заливка. Загрузка текстур из BMP (урок в разработке...)
Урок 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;
    }
}
1
Миниатюры
Уроки OpenGL - FAQ   Уроки OpenGL - FAQ  
Вложения
Тип файла: zip Код OpenGL-Win32 (C++).zip (9.1 Кб, 134 просмотров)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.03.2015, 04:30
Ответы с готовыми решениями:

Литература, уроки по OpenGL 3+
Подскажите пожалуйста литература, уроки и т.п. по OpenGL 3+. Желательно на...

Дайте ссылки на уроки по OpenGL в C#
Дайте ссылки на уроки по OpenGL в C#, пожалуйста

Уроки создания движков и редакторов на OpenGL+delphi
Сабж. Подскажите Уроки или киньте исходники движков, написанных на делфи с...

Создаю игру с научным уколоном на C++/opengl. Как подключить openGL и добиться кроссплатформенности
Я читал про opengl - для его инициализации нужно создавать windows - окно. Для...

(2 главы перевода книги доступно) OpenGL Programming Guide, Version 4.3, 8th Edition - OpenGL
Продолжая тему с переводом книги...

12
hays
26.03.2015, 09:49
  #2

Не по теме:

Вот если ты покажешь скажем как можно с помощью OpenGL более менее крупное приложение

Кликните здесь для просмотра всего текста
Скажем что то вроде приложение которое загружает мир из .OBJ файла можно передвигаться (WASD+mouse) имеет коллизию с этим миром тогда это чего то стоить а гайдов как рисовать "Квадрат" Over9000 в интернете....

0
Смолевич
26.03.2015, 14:12  [ТС]
  #3

Не по теме:

hays, ну, здесь уже своим движком попахивает...
Про это, возможно, даже отдельное FAQ будет...
Кстати, крупных приложений с открытым кодом - полно... Что-то их неохотно смотрят...

И, этот FAQ, - не совсем, гайд... Образно выражаясь, я здесь стараюсь писать не "как сделать", а, "как делается"...

Если у кого-нибудь есть ко мне вопросы, предложения, попрошу - в ЛС.
Чрезмерный оффтоп, опубликованный в теме - в дальнейшем, может быть почищен...

0
Смолевич
94 / 53 / 5
Регистрация: 19.07.2014
Сообщений: 416
26.03.2015, 18:33  [ТС] #4
Урок 2. GLUT vs WinAPI. Будь проще...

О GLUT


GLUT (OpenGL Utility Toolkit) - библиотека утилит, надстройка над WinAPI, позволяющая легко и просто создать окно OpenGL и настроить его на обработку рендеринга (WM_PAINT), клавиатуры (WM_KEYDOWN), и др., не используя, WinAPI.
Кроме того, библиотека GLUT является кроссплатформенной (на Windows использует WinAPI, а, на других ОС - API этих ОС), поэтому, облегчает портирование приложений с Windows - на другие ОС.

В отличие от opengl32.dll, glut32.dll не входит в Windows, а, glut.h и glut32.lib - не входят в Windows SDK (Visual Studio). Но, все 3 файла (все необходимое для использования GLUT на Windows), можно скачать здесь.
Файл glut32.dll помещают рядом с EXE, а, glut32.lib и glut.h - рядом с *.cpp.

Основная задача GLUT - именно упрощение и укорачивание кода, обеспечение возможности не отвлекаться на посторонние моменты (например, регистрацию и созданию окна WinAPI), а, сосредоточиться на графике OpenGL...
Взгляните на код... Сами увидите, что, он стал проще и понятнее...

В дальнейших уроках, будет использоваться, в основном, GLUT, поскольку, он почти полностью покрывает возможности WinAPI, и значительно упрощает разработку.



Сделаем то же, что и в Уроке 1, но, используя GLUT, вместо, WinAPI:

Код (С++)


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
#define UNICODE
 
// WinAPI
#include <Windows.h>
#include <tchar.h>
 
// OpenGL
#pragma comment(lib, "opengl32.lib")
 
// GLUT
#pragma comment(lib, "glut32.lib")
#include "glut.h"
 
int Angle = 0;
 
// Функции для работы с OpenGL/GLUT
void GLInit();
void GLRenderScene();
void GLKeyDown(unsigned char key, int x, int y);
 
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nShowCmd)
{
    // Аргументы командной строки (путь к EXE)
    char *argv0 = new char[512];
    GetModuleFileNameA(0, argv0, 512);
 
    // Число аргументов (один только путь к EXE, поэтому, argc = 1)
    int argc = 1;
 
    // Инициализация GLUT, для данного EXE
    glutInit(&argc, &argv0);
 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_SINGLE | GLUT_RGB);
    
    // Координаты и размер окна GLUT
    glutInitWindowPosition(200, 200);
    glutInitWindowSize(400, 400);
    
    // Создание окна GLUT
    glutCreateWindow("");
 
    // Обработчик рендеринга (вызывается при отрисовке окна, аналогично WM_PAINT)
    glutDisplayFunc(GLRenderScene);
 
    // Обработчик клавитуры (при WM_KEYDOWN)
    glutKeyboardFunc(GLKeyDown);
 
    // Инициализация OpenGL
    GLInit();
 
    // Главный цикл приложения
    glutMainLoop();
 
    return 0;
}
 
void GLInit()
{
    // Цвет фона - черный
    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);
 
    // Цвет прямоугольника - темно-зеленый:
    glColor3f(0.0, 0.5, 0.0);
 
    // Рисование прямоугольника
    glBegin(GL_POLYGON);
    glVertex2f(0, 0); // Левый-нижний угол
    glVertex2f(0, 1.0); // Левый-верхний угол
    glVertex2f(0.5, 1.0); // Правый-верхний угол
    glVertex2f(0.5, 0); // Правый-нижний угол
    glEnd();
 
    glutSwapBuffers();
}
 
void GLKeyDown(unsigned char key, int x, int y)
{
    Angle += 5; // Увеличиваем угол поворота на 5 градусов
 
    glutPostRedisplay(); // Перерисовываем окно
}


Сделаем то же самое и на Visual C#, новом для нашего FAQ языке.
Вместо opengl32.lib (которого для C# нет), будем использовать библиотеку Tao.OpenGL, а, вместо glut.h, glut32.dll и glut32.lib - библиотеку Tao.FreeGlut.
Обе библиотеки, можно скачать на официальном сайте Tao Framework.

Код (Visual C#)


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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using Tao.OpenGl;
using Tao.FreeGlut;
 
namespace OpenGL_GLUT_Tao__C_Sharp_
{
    class Program
    {
        static int Angle = 0;
 
        static void Main(string[] args)
        {
            // Инициализация GLUT
            Glut.glutInit();
 
            Glut.glutInitDisplayMode(Glut.GLUT_DOUBLE | Glut.GLUT_RGB);
 
            // Координаты и размер окна GLUT
            Glut.glutInitWindowPosition(200, 200);
            Glut.glutInitWindowSize(400, 400);
 
            // Создание окна GLUT
            Glut.glutCreateWindow("");
 
            // Обработчик рендеринга (вызывается при отрисовке окна, аналогично WM_PAINT)
            Glut.glutDisplayFunc(GLRenderScene);
 
            // Обработчик клавитуры (при WM_KEYDOWN)
            Glut.glutKeyboardFunc(GLKeyDown);
 
            // Инициализация OpenGL
            GLInit();
 
            // Главный цикл приложения
            Glut.glutMainLoop();
        }
 
        static void GLInit()
        {
            // Цвет фона - черный
            Gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        }
 
        static void GLRenderScene()
        {
            // Очищаем буфер цвета и глубины
            Gl.glClear(Gl.GL_COLOR_BUFFER_BIT | Gl.GL_DEPTH_BUFFER_BIT);
 
            Gl.glLoadIdentity();
 
            // Поворачиваем сцену на угол Angle, по осям X (1.0), Y (1.0), но не Z (0.0)
            Gl.glRotatef(Angle, 1.0f, 1.0f, 0.0f);
 
            // Цвет прямоугольника - темно-зеленый:
            Gl.glColor3f(0.0f, 0.5f, 0.0f);
 
            // Рисование прямоугольника
            Gl.glBegin(Gl.GL_POLYGON);
            Gl.glVertex2f(0, 0); // Левый-нижний угол
            Gl.glVertex2f(0, 1.0f); // Левый-верхний угол
            Gl.glVertex2f(0.5f, 1.0f); // Правый-верхний угол
            Gl.glVertex2f(0.5f, 0); // Правый-нижний угол
            Gl.glEnd();
 
            Glut.glutSwapBuffers();
        }
 
        static void GLKeyDown(byte key, int x, int y)
        {
            Angle += 5; // Увеличиваем угол поворота на 5 градусов
 
            Glut.glutPostRedisplay(); // Перерисовываем окно
        }
    }
}
0
Вложения
Тип файла: zip Код OpenGL-GLUT (C++).zip (75.5 Кб, 53 просмотров)
Тип файла: zip Код OpenGL-GLUT-Tao (C Sharp).zip (297.6 Кб, 22 просмотров)
Смолевич
94 / 53 / 5
Регистрация: 19.07.2014
Сообщений: 416
28.03.2015, 11:58  [ТС] #5
Урок 3. Круг, окружность, эллипс. Рисование композиций из нескольких разных фигур

Код


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
#define UNICODE
 
// WinAPI
#include <Windows.h>
#include <tchar.h>
 
// OpenGL
#pragma comment(lib, "opengl32.lib")
 
// GLUT
#pragma comment(lib, "glut32.lib")
#include "glut.h"
 
// Other
#include <math.h>
 
int Angle = 0;
 
// Функции для работы с OpenGL/GLUT
void GLInit();
void GLRenderScene();
void GLKeyDown(unsigned char key, int x, int y);
 
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nShowCmd)
{
    // Аргументы командной строки (путь к EXE)
    char *argv0 = new char[512];
    GetModuleFileNameA(0, argv0, 512);
 
    int argc = 1;
 
    // Инициализация GLUT
    glutInit(&argc, &argv0);
 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_SINGLE | GLUT_RGB);
    
    // Координаты и размер окна GLUT
    glutInitWindowPosition(200, 200);
    glutInitWindowSize(400, 400);
    
    // Создание окна
    glutCreateWindow("");
 
    // Обработчик рендеринга
    glutDisplayFunc(GLRenderScene);
 
    // Обработчик клавитуры
    glutKeyboardFunc(GLKeyDown);
 
    // Инициализация OpenGL
    GLInit();
 
    // Главный цикл
    glutMainLoop();
 
    return 0;
}
 
void GLInit()
{
    // Цвет фона - черный
    glClearColor(0.0, 0.0, 0.0, 1.0);
}
 
void GLRenderScene()
{
    // Очищаем буферы
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glLoadIdentity();
 
    // ------------------ Нарисуем круг -------------------
    // --------------- зеленый, по центру, ----------------
    // --- с возможностью поворота по X и Y клавиатурой ---
 
    // Цвет
    glColor3f(0.0, 1.0, 0.0);
 
    // Поворот
    glRotatef(Angle, 1.0, 1.0, 0.0);
 
    // Начало рисования круга радиусом 0.25
    // GL_POLYGON - для круга, GL_LINE_LOOP - для незакрашенной окружности
    glBegin(GL_POLYGON);
 
    // c - число сегментов окружности
    // чем выше c, тем выше качество тем бОльшей окружности, но, тем дольше выполняется цикл for
    int segCount = 90;
 
    // okrW, okrH - размеры окружности
    // Могут быть не равны - получится эллипс
    float okrW = 0.25;
    float okrH = 0.25;
 
    for(int i = 0; i < segCount; i++)
    {
        // Окружность/эллипс - описывается параметрическим уравнением
        // X = Width * cos(theta),
        // Y = Height * sin(theta),
        // где 0 <= theta < 2 * pi
        // См. Википедию, и учебники геометрии
 
        float theta = (2 * 3.1415926f) * (float(i) / float(segCount));
 
        float X = okrW * cosf(theta);
        float Y = okrH * sinf(theta);
 
        glVertex2f(X, Y);
 
    }
 
    // Конец рисования круга
    glEnd();
 
    // ---------- Теперь, нарисуем прямоугольник ----------
    // ---- красный, с лев.верхом в точке [0.5; 0.5], -----
    // ------------- без возможности поворота -------------
 
    // Цвет
    glColor3f(1.0, 0.0, 0.0);
 
    // Поворот на -Angle градусов
    // Angle - Angle = 0
    // Поэтому Angle из предыдущего вызова glRotatef (для круга) - на прямоугольник не влияет
    glRotatef(-Angle, 1.0, 1.0, 0.0);
 
    // Этой функцией ставим центр Oxyz
    // перемещаем его на заданные расстояния X, Y, Z от исх.точки
    glTranslatef(0.5, 0.5, 0);
 
    // Рисование
    // функция glTranslatef (указание координат лево-верха до отрисовки) делает код прозрачнее:
    // сначала координаты лев.верха (glTranslatef), затем - размеры 0.25x0.25 (glVertex2f)
    // Сравните с кодом Уроков 1 и 2
    glBegin(GL_POLYGON);
    glVertex2f(0.0, 0.0); // Лев.верх по центру
    glVertex2f(0.25, 0.0);
    glVertex2f(0.25, -0.25);
    glVertex2f(0.0, -0.25);
    glEnd();
 
    // ----------- И еще один, такой же, прямоугольник -----------
    // --------------- в другой точке - -0.5 и -0.5 --------------
 
    // Цвет не задаем, поскольку, задан выше
    
    // Поворот, тоже, задан выше
 
    // Центр Oxyz должен быть [-0.5; -0.5]
    // Но, после предыдущего glTranslatef, он находиться в [0.5; 0.5], поэтому:
    // Ox = 0.5 + (-1.0) = -0.5
    // и также Oy
    glTranslatef(-1.0, -1.0, 0);
 
    // Рисуем
    glBegin(GL_POLYGON);
    glVertex2f(0.0, 0.0); // Лев.верх по центру
    glVertex2f(0.25, 0.0);
    glVertex2f(0.25, -0.25);
    glVertex2f(0.0, -0.25);
    glEnd();
 
    glutSwapBuffers();
}
 
void GLKeyDown(unsigned char key, int x, int y)
{
    Angle += 5; // Увеличиваем угол поворота на 5 градусов
 
    glutPostRedisplay(); // Перерисовываем окно
}
0
Миниатюры
Уроки OpenGL - FAQ  
Вложения
Тип файла: zip Код OpenGL-CircleOther (C++).zip (84.0 Кб, 44 просмотров)
Смолевич
94 / 53 / 5
Регистрация: 19.07.2014
Сообщений: 416
01.04.2015, 04:33  [ТС] #6
Урок 4. Точка, линия, ломаная линия, кривая, замкнутая кривая. Толщина линии

Нарисуем красную линию, красную точку, белую ломанную линию, толщиной 4 пикселя, и кривую линию (формула кривой: y = x^2).

Код


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
#define UNICODE
 
// WinAPI
#include <Windows.h>
#include <tchar.h>
 
// OpenGL
#pragma comment(lib, "opengl32.lib")
 
// GLUT
#pragma comment(lib, "glut32.lib")
#include "glut.h"
 
// Other
#include <math.h>
 
int Angle = 0;
 
// Функции для работы с OpenGL/GLUT
void GLInit();
void GLRenderScene();
void GLKeyDown(unsigned char key, int x, int y);
 
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nShowCmd)
{
    // Аргументы командной строки (путь к EXE)
    char *argv0 = new char[512];
    GetModuleFileNameA(0, argv0, 512);
 
    int argc = 1;
 
    // Инициализация GLUT
    glutInit(&argc, &argv0);
 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_SINGLE | GLUT_RGB);
 
    // Координаты и размер окна GLUT
    glutInitWindowPosition(200, 200);
    glutInitWindowSize(400, 400);
 
    // Создание окна
    glutCreateWindow("");
 
    // Обработчик рендеринга
    glutDisplayFunc(GLRenderScene);
 
    // Обработчик клавитуры
    glutKeyboardFunc(GLKeyDown);
 
    // Инициализация OpenGL
    GLInit();
 
    // Главный цикл
    glutMainLoop();
 
    return 0;
}
 
void GLInit()
{
    // Цвет фона - черный
    glClearColor(0.0, 0.0, 0.0, 1.0);
}
 
void GLRenderScene()
{
    // Очищаем буферы
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glLoadIdentity();
 
    // Поворот
    glRotatef(Angle, 1.0, 1.0, 0.0);
 
    // --- Линия ---
    glColor3f(1.0, 0.0, 0.0);
    glBegin(GL_LINES);
    glVertex3f(0.3, -0.2, 0.0);
    glVertex3f(-0.9, -0.22, 0.0);
    glEnd();
 
    // --- Точка ---
    glBegin(GL_POINTS);
    glVertex3f(0.5, 0.5, 0.0);
    glEnd();
 
    // --- Ломаная ---
    glColor3f(1.0, 1.0, 1.0);
    glLineWidth(4); // Толщина линии - 4 пкс
    glBegin(GL_LINES); // Или GL_LINE_STRIP
    // Фрагмент 1
    glVertex3f(0.0, 0.0, 0.0); // Начало фрагмента 1
    glVertex3f(0.5, 0.0, 0.0); // Конец фрагмента 1
    // Фрагмент 2
    glVertex3f(0.5, 0.0, 0.0); // Начало 2. При GL_LINE_STRIP можно не задавать
    glVertex3f(0.3, 0.5, 0.0); // Конец 2
    glEnd();
 
    // --- Кривая ---
    glColor3f(0.0, 1.0, 0.0);
    glLineWidth(1); // Толщина линии - снова 1 пкс
    glBegin(GL_LINE_STRIP); // Или GL_LINE_LOOP - для замкнутой фигуры, или GL_POLYGON - для замкнутой закрашенной фигуры
    float x = -0.1;
    float y;
    for (x; x > -0.5; x-=0.001)
    {
        y = x * x;
        glVertex3f(x, y, 0.0);
    }
    glEnd();
 
    glutSwapBuffers();
}
 
void GLKeyDown(unsigned char key, int x, int y)
{
    Angle += 5; // Увеличиваем угол поворота на 5 градусов
 
    glutPostRedisplay(); // Перерисовываем окно
}
0
Миниатюры
Уроки OpenGL - FAQ  
Вложения
Тип файла: zip OpenGL-Lines (C++).zip (83.1 Кб, 18 просмотров)
Смолевич
94 / 53 / 5
Регистрация: 19.07.2014
Сообщений: 416
02.04.2015, 22:25  [ТС] #7
Урок 5. Рисование первой 3D-фигуры. Параллелепипед

О рисовании трехмерных фигур


Трехмерная фигура состоит из двухмерных примитивов (например, многоугольников), помещенных в трехмерном мире. Вершины примитива в трехмерном мире имеют не только X- и Y-координаты, но и, Z-координату.
К примеру, если вершины передней (ближайшей к нам) грани куба - имеют Z = 0, то, вершины задней грани куба - могут иметь Z > 0, а, вершины остальных (боковых) сторон куба - будут иметь различное Z: две передние вершины каждой грани - Z = 0, а 2 задние вершины каждой грани - Z > 0).

Перед рисованией 3D-фигур необходимо включить тест глубины:
C++
1
glEnable(GL_DEPTH_TEST);
При включенном тесте глубины, OpenGL определяет, какие грани 3D-фигуры располагаются ближе к нам, чем остальные - и рисует их поверх, чтобы, передние грани загораживали задние (более глубокие) грани, и, задние грани не виднелись через передние.



Нарисуем параллелепипед с разноцветными гранями, в формациях квадрата из уроков 1-2.

Код


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
#define UNICODE
 
// WinAPI
#include <Windows.h>
#include <tchar.h>
 
// OpenGL
#pragma comment(lib, "opengl32.lib")
 
// GLUT
#pragma comment(lib, "glut32.lib")
#include "glut.h"
 
// Other
#include <math.h>
 
int Angle = 0;
 
// Функции для работы с OpenGL/GLUT
void GLInit();
void GLRenderScene();
void GLKeyDown(unsigned char key, int x, int y);
 
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nShowCmd)
{
    // Аргументы командной строки (путь к EXE)
    char *argv0 = new char[512];
    GetModuleFileNameA(0, argv0, 512);
 
    int argc = 1;
 
    // Инициализация GLUT
    glutInit(&argc, &argv0);
 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_SINGLE | GLUT_RGB);
 
    // Координаты и размер окна GLUT
    glutInitWindowPosition(200, 200);
    glutInitWindowSize(400, 400);
 
    // Создание окна
    glutCreateWindow("");
 
    // Обработчик рендеринга
    glutDisplayFunc(GLRenderScene);
 
    // Обработчик клавитуры
    glutKeyboardFunc(GLKeyDown);
 
    // Инициализация OpenGL
    GLInit();
 
    // Главный цикл
    glutMainLoop();
 
    return 0;
}
 
void GLInit()
{
    // Цвет фона - черный
    glClearColor(0.0, 0.0, 0.0, 1.0);
}
 
void GLRenderScene()
{
    // Очищаем буферы
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glLoadIdentity();
 
    // Включаем тест глубины,
    // чтобы грани 3D-фигур - рисовались непрозрачными, и не просвечивали
    glEnable(GL_DEPTH_TEST);
 
    // Поворот
    glRotatef(Angle, 1.0, 1.0, 0.0);
 
    // -------- Рисование параллелепипеда ----------
    // Длина x высота x глубина:
    //   0.5    1.0      0.25
 
    // Передняя грань
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glBegin(GL_POLYGON);
    glVertex3f(0, 0, 0); // ЛН
    glVertex3f(0, 1.0, 0); // ЛВ
    glVertex3f(0.5, 1.0, 0); // ПВ
    glVertex3f(0.5, 0, 0); // ПН
    glEnd();
 
    // Задняя грань
    // Та же передняя, только, Z = 0.25, а, не 0
    glColor3f(1.0, 0.0, 0.0); // красный
    glBegin(GL_POLYGON);
    glVertex3f(0, 0, 0.25); // ЛН
    glVertex3f(0, 1.0, 0.25); // ЛВ
    glVertex3f(0.5, 1.0, 0.25); // ПВ
    glVertex3f(0.5, 0, 0.25); // ПН
    glEnd();
 
    // Левая грань
    glColor3f(1.0, 1.0, 0.0); // желтый
    glBegin(GL_POLYGON);
    glVertex3f(0, 0, 0.0); // Перед-низ
    glVertex3f(0, 1.0, 0.0); // Перед-верх
    glVertex3f(0, 1.0, 0.25); // Зад-верх
    glVertex3f(0, 0, 0.25); // Зад-низ
    glEnd();
 
    // Правая грань
    // Та же левая, только, X = 0.5
    glColor3f(0.0, 1.0, 1.0); // Голубой
    glBegin(GL_POLYGON);
    glVertex3f(0.5, 0, 0.0); // Перед-низ
    glVertex3f(0.5, 1.0, 0.0); // Перед-верх
    glVertex3f(0.5, 1.0, 0.25); // Зад-верх
    glVertex3f(0.5, 0, 0.25); // Зад-низ
    glEnd();
    
    // Верхняя грань
    glColor3f(1.0, 0.0, 1.0); // Розовый
    glBegin(GL_POLYGON);
    glVertex3f(0, 1.0, 0.0); // Перед-лево
    glVertex3f(0.5, 1.0, 0.0); // Перед-право
    glVertex3f(0.5, 1.0, 0.25); // Зад-право
    glVertex3f(0, 1.0, 0.25); // Зад-лево
    glEnd();
 
    // Нижняя грань
    // Та же верхняя, только, Y = 0
    glColor3f(1.0, 1.0, 1.0); // Белый
    glBegin(GL_POLYGON);
    glVertex3f(0, 0.0, 0.0); // Перед-лево
    glVertex3f(0.5, 0.0, 0.0); // Перед-право
    glVertex3f(0.5, 0.0, 0.25); // Зад-право
    glVertex3f(0, 0.0, 0.25); // Зад-лево
    glEnd();
 
    glutSwapBuffers();
}
 
void GLKeyDown(unsigned char key, int x, int y)
{
    Angle += 5; // Увеличиваем угол поворота на 5 градусов
 
    glutPostRedisplay(); // Перерисовываем окно
}
0
Миниатюры
Уроки OpenGL - FAQ  
Вложения
Тип файла: zip OpenGL-3D (C++).zip (83.1 Кб, 70 просмотров)
snake32
03.04.2015, 02:08
  #8

Не по теме:

Цитата Сообщение от Смолевич Посмотреть сообщение
Перед рисованией 3D-фигур необходимо включить тест глубины:
glEnable(GL_DEPTH_TEST);
чтобы грани рисовались непрозрачными, и не просвечивали
Тест глубины умеет лишь определять какие фрагменты примитива оказались поверх остальных - уже нарисованных, их и рисует. За прозрачность отвечает другая ф-ия OpenGL - Blending.

0
Смолевич
03.04.2015, 03:27  [ТС]
  #9

Не по теме:

snake32, спасибо, за более информативное определение теста глубины.
А, под непрозрачностью, я имел в виду - просто "непросвечиваемость"... Блендинг - ни при делах...

0
Смолевич
94 / 53 / 5
Регистрация: 19.07.2014
Сообщений: 416
05.05.2015, 03:24  [ТС] #10
Урок 6. Градиентная заливка. Полноэкранный режим. Клавиша Esc

О градиентной заливке


Чтобы задать градиентную заливку, нужно разным вершинам полигона задать разные цвета. Если перед тем, как задавать одну из вершин через glVertex3f, вызвать glColor3f, то эта и следующая вершины, будут заданного цвета.

Рассмотрим несколько разных градиентов, на примере прямоугольника.
Если верхние вершины прямоугольника сделать красными, а нижние - зелеными, то прямоугольник будет залит горизонтальным красно-зеленым градиентом: верхняя часть - красная, нижняя - зеленая.
Если левые вершины сделать красными, а правые - зелеными, то прямоугольник будет залит вертикальным красно-зеленым градиентом: левая часть - красная, правая - зеленая.
Если все вершины сделать разноцветными, то полигон будет поделен на 4 равные части соответствующих цветов, плавно переходящие друг в друга. Получится радиальная градиентная композиция.
Также, можно создать линейную градиентную композицию, если разместить дополнительные точки (вершины), на сторонах прямоугольника.



О полноэкранном режиме


Функция
C++
1
glutFullScreen();
разворачивает окно, созданное GLUTом, во весь экран.
Обратите внимание на слово "созданное". Функция должна вызываться - после glutCreateWindow, а не до, и не взамен.



Об обработке отдельных клавиш


Наши предыдущие приложения - одинаково реагировали на нажатия любых клавиш и комбинаций клавиш:
C++
1
2
3
4
5
6
void GLKeyDown(unsigned char key, int x, int y)
{
    // ...
    // TODO Действие при нажатии любой клавиши
    // ...
}
Исключения составляли лишь такие клавиши, как F1-F12, Ctrl или Shift, которые не обрабатывались вообще.

В этом уроке, мы рассматриваем полноэкранный режим. Приложение теперь не закроешь мышкой. Назначим специальную клавишу, которая будет

закрывать приложение, а не, поворачивать сцену, как остальные клавиши. Конечно же, это будет клавиша Esc:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
void GLKeyDown(unsigned char key, int x, int y)
{
    if (key == VK_ESCAPE) // Если нажата клавиша Escape. Библиотека GLUT на Windows поддерживает виртуальные коды WinAPI - VK_***
    {
        exit(0); // Выход
    }
    else // Если нажата любая другая клавиша
    {
        // ...
        // TODO Поворот сцены - действие при нажатии любой клавиши, кроме Esc
        // ...
    }
}


Слегка изменим программу из урока 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
#define UNICODE
 
// WinAPI
#include <Windows.h>
#include <tchar.h>
 
// OpenGL
#pragma comment(lib, "opengl32.lib")
 
// GLUT
#pragma comment(lib, "glut32.lib")
#include "glut.h"
 
// Other
#include <math.h>
 
int Angle = 0;
 
// Функции для работы с OpenGL/GLUT
void GLInit();
void GLRenderScene();
void GLKeyDown(unsigned char key, int x, int y);
 
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nShowCmd)
{
    // Аргументы командной строки (путь к EXE)
    char *argv0 = new char[512];
    GetModuleFileNameA(0, argv0, 512);
 
    int argc = 1;
 
    // Инициализация GLUT
    glutInit(&argc, &argv0);
 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_SINGLE | GLUT_RGB);
 
    // Создание окна
    glutCreateWindow("");
 
    // Развертываение созданного окна в полный экран
    glutFullScreen();
 
    // Обработчик рендеринга
    glutDisplayFunc(GLRenderScene);
 
    // Обработчик клавитуры
    glutKeyboardFunc(GLKeyDown);
 
    // Инициализация OpenGL
    GLInit();
 
    // Главный цикл
    glutMainLoop();
 
    return 0;
}
 
void GLInit()
{
    // Цвет фона - черный
    glClearColor(0.0, 0.0, 0.0, 1.0);
}
 
void GLRenderScene()
{
    // Очищаем буферы
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glLoadIdentity();
 
    // Включаем тест глубины,
    // чтобы грани 3D-фигур - рисовались непрозрачными
    glEnable(GL_DEPTH_TEST);
 
    // Поворот
    glRotatef(Angle, 1.0, 1.0, 0.0);
 
    // -------- Рисование параллелепипеда ----------
    // Длина x высота x глубина:
    //   0.5    1.0      0.25
 
    // Передняя грань
    glBegin(GL_POLYGON);
 
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0, 0, 0); // ЛН
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0, 1.0, 0); // ЛВ
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0.5, 1.0, 0); // ПВ
 
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0.5, 0, 0); // ПН
 
    glEnd();
 
    // Задняя грань
    // Та же передняя, только, Z = 0.25, а, не 0
    glBegin(GL_POLYGON);
 
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0, 0, 0.25); // ЛН
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0, 1.0, 0.25); // ЛВ
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0.5, 1.0, 0.25); // ПВ
 
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0.5, 0, 0.25); // ПН
    glEnd();
 
    // Левая грань
    glBegin(GL_POLYGON);
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0, 0, 0.0); // Перед-низ
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0, 1.0, 0.0); // Перед-верх
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0, 1.0, 0.25); // Зад-верх
 
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0, 0, 0.25); // Зад-низ
    glEnd();
 
    // Правая грань
    // Та же левая, только, X = 0.5
    glBegin(GL_POLYGON);
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0.5, 0, 0.0); // Перед-низ
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0.5, 1.0, 0.0); // Перед-верх
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0.5, 1.0, 0.25); // Зад-верх
    
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0.5, 0, 0.25); // Зад-низ
    glEnd();
    
    // Верхняя грань
    glBegin(GL_POLYGON);
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0, 1.0, 0.0); // Перед-лево
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0.5, 1.0, 0.0); // Перед-право
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0.5, 1.0, 0.25); // Зад-право
 
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0, 1.0, 0.25); // Зад-лево
    glEnd();
 
    // Нижняя грань
    // Та же верхняя, только, Y = 0
    glBegin(GL_POLYGON);
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0, 0.0, 0.0); // Перед-лево
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0.5, 0.0, 0.0); // Перед-право
 
    glColor3f(1.0, 0.0, 0.0); // красный
    glVertex3f(0.5, 0.0, 0.25); // Зад-право
 
    glColor3f(0.0, 1.0, 0.0); // зеленый
    glVertex3f(0, 0.0, 0.25); // Зад-лево
    glEnd();
 
    glutSwapBuffers();
}
 
void GLKeyDown(unsigned char key, int x, int y)
{
    if (key == VK_ESCAPE) // Если нажата клавиша Escape
    {
        exit(0); // Выход
    }
    else // Если нажата любая другая клавиша
    {
        Angle += 5; // Увеличиваем угол поворота на 5 градусов
 
        glutPostRedisplay(); // Перерисовываем окно
    }
}
0
Миниатюры
Уроки OpenGL - FAQ  
Вложения
Тип файла: zip OpenGL-Gradient (C++).zip (90.7 Кб, 21 просмотров)
Смолевич
94 / 53 / 5
Регистрация: 19.07.2014
Сообщений: 416
30.11.2015, 11:06  [ТС] #11
Урок 7. Текстурная заливка. Загрузка текстур из BMP (урок в разработке...)

BMP - достаточно простой формат. Его бинарная структура, подробно описана в Википедии на русском языке, и, для большей наглядности, - может быть легко проверена экспериментальным путем, с помощью HEX-редактора.
Что позволяет реализовать загрузку из него пикселей для текстуры - вручную, без каких-либо специальных библиотек.

Код (в папке проекта и в папке с EXE, должен лежать файл Texture.bmp)


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
#define UNICODE
 
// WinAPI
#include <Windows.h>
#include <tchar.h>
 
// OpenGL
#pragma comment(lib, "opengl32.lib")
 
// GLUT
#pragma comment(lib, "glut32.lib")
#include "glut.h"
 
// Other
#include <math.h>
#include <stdio.h>
 
int Angle = 0;
 
// Функции для работы с OpenGL/GLUT
void GLInit();
void GLRenderScene();
void GLKeyDown(unsigned char key, int x, int y);
 
// Прочие функции
GLuint InitTextureFromBMP(const char * imagepath);
 
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPWSTR lpCmdLine, int nShowCmd)
{
    // Аргументы командной строки (путь к EXE)
    char *argv0 = new char[512];
    GetModuleFileNameA(0, argv0, 512);
 
    int argc = 1;
 
    // Инициализация GLUT
    glutInit(&argc, &argv0);
 
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_SINGLE | GLUT_RGB);
 
    // Координаты и размер окна GLUT
    glutInitWindowPosition(200, 200);
    glutInitWindowSize(400, 400);
 
    // Создание окна
    glutCreateWindow("");
 
    // Обработчик рендеринга
    glutDisplayFunc(GLRenderScene);
 
    // Обработчик клавитуры
    glutKeyboardFunc(GLKeyDown);
 
    // Инициализация OpenGL
    GLInit();
 
    // Главный цикл
    glutMainLoop();
 
    return 0;
}
 
void GLInit()
{
    // Цвет фона - черный
    glClearColor(0.0, 0.0, 0.0, 1.0);
 
    // Загрузка текстуры
    InitTextureFromBMP("Texture.bmp");
}
 
void GLRenderScene()
{
    // Очищаем буферы
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
    glLoadIdentity();
 
    // Включаем тест глубины,
    // чтобы грани 3D-фигур - рисовались непрозрачными
    glEnable(GL_DEPTH_TEST);
 
    // Поворот
    glRotatef(Angle, 1.0, 1.0, 0.0);
 
    // -------- Рисование параллелепипеда ----------
    // Длина x высота x глубина:
    //   0.5    1.0      0.25
 
    ::glEnable(GL_TEXTURE_2D);
 
    // Передняя грань
    glBegin(GL_POLYGON);
    glTexCoord2f(0.0, 0.0);
    glVertex3f(0, 0, 0); // ЛН
    glTexCoord2f(0.0, 2.0);
    glVertex3f(0, 1.0, 0); // ЛВ
    glTexCoord2f(2.0, 2.0);
    glVertex3f(0.5, 1.0, 0); // ПВ
    glTexCoord2f(2.0, 0.0);
    glVertex3f(0.5, 0, 0); // ПН
    glEnd();
 
    ::glDisable(GL_TEXTURE_2D);
 
    // Задняя грань
    // Та же передняя, только, Z = 0.25, а, не 0
    glColor3f(1.0, 0.0, 0.0); // красный
    glBegin(GL_POLYGON);
    glVertex3f(0, 0, 0.25); // ЛН
    glVertex3f(0, 1.0, 0.25); // ЛВ
    glVertex3f(0.5, 1.0, 0.25); // ПВ
    glVertex3f(0.5, 0, 0.25); // ПН
    glEnd();
 
    // Левая грань
    glColor3f(1.0, 1.0, 0.0); // желтый
    glBegin(GL_POLYGON);
    glVertex3f(0, 0, 0.0); // Перед-низ
    glVertex3f(0, 1.0, 0.0); // Перед-верх
    glVertex3f(0, 1.0, 0.25); // Зад-верх
    glVertex3f(0, 0, 0.25); // Зад-низ
    glEnd();
 
    // Правая грань
    // Та же левая, только, X = 0.5
    glColor3f(0.0, 1.0, 1.0); // Голубой
    glBegin(GL_POLYGON);
    glVertex3f(0.5, 0, 0.0); // Перед-низ
    glVertex3f(0.5, 1.0, 0.0); // Перед-верх
    glVertex3f(0.5, 1.0, 0.25); // Зад-верх
    glVertex3f(0.5, 0, 0.25); // Зад-низ
    glEnd();
    
    // Верхняя грань
    glColor3f(1.0, 0.0, 1.0); // Розовый
    glBegin(GL_POLYGON);
    glVertex3f(0, 1.0, 0.0); // Перед-лево
    glVertex3f(0.5, 1.0, 0.0); // Перед-право
    glVertex3f(0.5, 1.0, 0.25); // Зад-право
    glVertex3f(0, 1.0, 0.25); // Зад-лево
    glEnd();
 
    // Нижняя грань
    // Та же верхняя, только, Y = 0
    glColor3f(1.0, 1.0, 1.0); // Белый
    glBegin(GL_POLYGON);
    glVertex3f(0, 0.0, 0.0); // Перед-лево
    glVertex3f(0.5, 0.0, 0.0); // Перед-право
    glVertex3f(0.5, 0.0, 0.25); // Зад-право
    glVertex3f(0, 0.0, 0.25); // Зад-лево
    glEnd();
 
    glutSwapBuffers();
}
 
void GLKeyDown(unsigned char key, int x, int y)
{
    Angle += 5; // Увеличиваем угол поворота на 5 градусов
 
    glutPostRedisplay(); // Перерисовываем окно
}
 
GLuint InitTextureFromBMP(const char* filename)
{
    // Заголовок файла BMP
    char header[54];
 
    int dataPos; // Позиция в файле BMP, где заканчивается заголовок, и, начинаются пиксели
 
    int width, height;
    int imageSize; // width * height * 3 (т.к., каждый пиксель занимает 3 байта - B (синий), G (зеленый), R (красный))
 
    char* data; // Сюда будут читаться пиксели, из BMP
 
    // Открываем файл
    FILE * file = fopen(filename, "rb");
    if (!file)
    {
        MessageBox(0, L"Ошибка: Не удается открыть файл с текстурой.", 0, 0);
        return 0;
    }
 
    if (fread(header, 1, 54, file)!=54 )
    {
        MessageBox(0,L"Ошибка: Файл с текстурой поврежден. Не удается считать заголовок файла.",0,0);
        return false;
    }
 
    if (header[0] != 'B' || header[1] != 'M'){
        MessageBox(0,L"Ошибка: Файл с текстурой поврежден. Имеет неверный заголовок.",0,0);
        return 0;
    }
 
    dataPos    = *(int*)&(header[0x0A]);
    imageSize  = *(int*)&(header[0x22]);
    width      = *(int*)&(header[0x12]);
    height     = *(int*)&(header[0x16]);
 
    if (imageSize == 0)
        imageSize = width * height * 3;
    if (dataPos == 0)
        dataPos = 54;
 
    data = new char [imageSize];
    
    fread(data, 1, imageSize, file);
    
    fclose(file);
 
    GLuint textureID;
    glGenTextures(1, &textureID);
 
    // ------ Привязка текстуры и настройка ------
 
    glBindTexture(GL_TEXTURE_2D, textureID);
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
        GL_BGR_EXT, // BGR означает, что в считанных пикселях следует B и R (красный и синий) поменять местами (в формате BMP они перепутаны)
        GL_UNSIGNED_BYTE, data);
    
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
    // ------- Настройки масштабирования текстуры (под нужный размер) -------
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // При уменьшении - сглаживать
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // При увеличении - сглаживать
 
    return textureID;
}
1
Миниатюры
Уроки OpenGL - FAQ  
Вложения
Тип файла: zip OpenGL-Texture (C++).zip (351.5 Кб, 50 просмотров)
Anteia
0 / 0 / 0
Регистрация: 17.04.2016
Сообщений: 3
17.04.2016, 18:29 #12
Доброго времени суток. У меня есть программа, которая рисует различные фигуры, различными методами. Возникла проблема при попытке сделать градиентную заливку для треугольника. Задаю красный и желтый цвета вершинам треугольника, а градиент отрисовывается из красного в черный. При этом градиентная заливка линии выполняется. Вот код:
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;
}
0
Anteia
0 / 0 / 0
Регистрация: 17.04.2016
Сообщений: 3
17.04.2016, 18:32 #13
Смолевич, доброго времени суток.
У меня есть программа, которая рисует различные фигуры, различными методами. Возникла проблема при попытке сделать градиентную заливку для треугольника. Задаю красный и желтый цвета вершинам треугольника, а градиент отрисовывается из красного в черный. При этом градиентная заливка линии выполняется. Вот код:
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;
}
0
17.04.2016, 18:32
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
17.04.2016, 18:32

Ошибки при подключение opengl, немного не связанные с opengl
#include &lt;windows.h&gt; #include &quot;stdafx.h&quot; #include &lt;gl/gl.h&gt; #include...

OpenGL + GlTools по книге OpenGL Суперкнига
В главе 4 есть пример с отрисовкой 3хмерного вращающегося тора. Вот код: void...

Сильно отличаются OpenGL ES и OpenGL и как?
Сильно отличаются OpenGL ES и OpenGL и как?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru