Дым — это очень полезный и красивый эффект, при этом совсем не сложный.
Исходные коды возьмите из урока «Камера: часть 5«.

Переходим к редактированию main.cpp:

// После всех инклудов добавим 2 переменных:
float g_FogDensity = 0.2f;          // Плотность дыма
bool  g_bFog = true;                // Включен или выключен дым// Изменяем функцию Init(); включим в ней дым. Прежде всего нужно выбрать
// цвет дыма. Так как это потенциально цвет RGBA, нужно установить 4 значения.
// По умолчанию они = (0,0,0,0), и нам нужно изменить их.
// Помещаем наши цвета в массив, т.к. ф-я glFogfv принимает их в таком виде.float fogColor[4] = {0.0f,0.0f,1.0f,1.0f};// Установим цвет мира таким же, как цвет тумана:
glClearColor(0, 0, 1, 1);// Передаём OpenGL массив цветов:
glFogfv(GL_FOG_COLOR, fogColor);// Теперь, имея цвет дыма, установим его режим. Я выбрал GL_EXP2, но по умолчанию
// установлен GL_EXP. Ещё есть GL_LINEAR. Попробуйте все, чтобы наглядно понять их.
// Смысл в том, что они просчитываются по-разному. Мне кажется, что «экспотенциальный»
// дым выглядит лучше всего. Его формула: (f=e^(-density * Z), где Z — позиция камеры.

glFogi(GL_FOG_MODE, GL_EXP2);// Изменим плотность дыма. По умолчанию она равна единице, но мы начнем с 0.2f:
glFogf(GL_FOG_DENSITY, g_FogDensity);

// FOG_HINT — опция, устанавливающая, как именно будет отрисован дым.
// Нам всё равно, так мы и скажем %) GL_DONT_CARE даёт возможность OpenGL
// выбрать, рисовать вершинный и пикселный дым. На выбор есть 2 опции: GL_FASTEST и GL_NICEST
glHint(GL_FOG_HINT, GL_DONT_CARE);

// Это важная часть. Тут мы устанавливаем расстояние от нашей камеры, на котором будет
// начинатся дым. Пространство вне START и END будет окрашено цветом дыма. Я обычно ставлю
// дальнее значение таким же, как и дистанция взгляда. Минимальное по умолчанию 0,
// и мы не будем его изменять.
glFogf(GL_FOG_START, 0);

// значение END по умолчанию единица, увеличим его:
glFogf(GL_FOG_END, 10.0f);

// Наконец, инициализировав все необходимое, включим дым:
glEnable(GL_FOG);

// Следующие изменения нужно внести в функцию WinProc, в секцию WM_KEYDOWN:
case WM_KEYDOWN:
switch (wParam)
{
// Ниже мы дадим возможность пользователю увеличивать и уменьшать
// плотность дыма нажатием ‘+’ и ‘-‘. После увеличения плотности
// нужно отослать новую информацию OpenGL вызовом glFogf().
// В функцию передаётся флаг GL_FOG_DENSITY и новая плотность.

case VK_ESCAPE:
PostQuitMessage(0);
break;

case VK_ADD:    // Если нажат плюс
g_FogDensity += 0.015f; // Увеличиваем плотность
glFogf(GL_FOG_DENSITY, g_FogDensity);   // Передадим её OpenGL
if(g_FogDensity > 1) g_FogDensity = 1;
break;

case VK_SUBTRACT:       // Если нажат минус
g_FogDensity -= 0.015f; // Уменьшим плотность
glFogf(GL_FOG_DENSITY, g_FogDensity);   // Передадим её OpenGL
// Убедимся, что не менее 0:
if(g_FogDensity < 0) g_FogDensity = 0;
break;

case ‘F’:   // Если нажата «F»
g_bFog = !g_bFog;// Установим переключатель в противоположное

if(g_bFog)  // если включен дым
glEnable(GL_FOG);
else        // иначе
glDisable(GL_FOG);
break;
}
break;
//////////////////////////////////////////

 

На этом всё. Пройдемся ещё раз по пунктам:

1) Нужно установить способ генерации дыма этой функцией: glFogi(GL_FOG_MODE, GL_EXP2);

2) Передаём OpenGL массив цвета дыма: glFogfv(GL_FOG_COLOR, fogColor);

3) Устанавливаем плотность дыма: glFogf(GL_FOG_DENSITY, g_FogDensity);

4) Способ создания дыма (GL_NICEST/GL_FASTEST/GL_DONT_CARE):
glHint(GL_FOG_HINT, GL_DONT_CARE);

5) Передаём OpenGL ближнюю и дальнюю дистанции отрисовки дыма:
glFogf(GL_FOG_START, 0);
glFogf(GL_FOG_END, 10.0f);

6) И, наконец, включаем дым: glEnable(GL_FOG);

Исходные коды к уроку