{
Хаха, эти два урока уже давно переведены, но их еще не выложили. Все давно ждут (Кто-то уже ждет?)
простая прозрачность
Подавляющее большинство специальных эффектов в OpenGL связано с тем или иным типом (цветового) смешивания.
Смешение цветов определяется как объединение цвета определенного пикселя с цветом соответствующего ему пикселя, нарисованного на экране.
Способ объединения двух цветов зависит от значений компонентов альфа-канала цвета и/или используемой функции смешивания цветов.
Альфа обычно является четвертым компонентом цвета в конце значения цвета.
В предыдущих уроках мы использовали GL_RGB для указания трех компонентов цвета.
Соответствующий GL_RGBA может указывать значение альфа-компонента.
Идя еще дальше, мы можем использовать glColor4f() вместо glColor3f().
Большинство людей согласны с тем, что компонент Альфа представляет прозрачность материала.
Это означает, что значение альфа 0,0 представляет собой полностью прозрачный материал.
Значение альфа 1,0 представляет собой полностью непрозрачный материал.
формула смешивания цветов
Если вас не интересует математика и вы просто хотите узнать, как добиться прозрачности, пропустите этот раздел.
Если вы хотите глубже понять, как работает смешивание (цветов), этот раздел для вас.
『Дополнение CKER: На самом деле это не сложно^-^. Формула в оригинальной статье следующая, пусть CKER расскажет о ней еще раз.
Фактически, основной принцип смешивания заключается в разделении цвета каждого пикселя и цвета фона изображения, подлежащего разделению, в соответствии с правилами RGB.
Согласно - цветовая составляющая RGB изображения * значение альфа + цветовая составляющая RGB фона * (значение 1-альфа)
-После смешивания по такой простой формуле полученные в результате смешивания компоненты RGB окончательно вновь объединяются. 』
Формула выглядит следующим образом:
(Рс Ср+Рд Др, Гс Сг+Гд Дг, Бс Сб+Бд Дб, Ас Са+Ад Да)
OpenGL вычисляет результат смешивания цветов этих двух пикселей в соответствии с приведенной выше формулой.
Строчные буквы s и r обозначают исходные и целевые пиксели соответственно. Заглавные буквы S и D — соответствующие коэффициенты смешения цветов.
Они определяют, как вы смешиваете цвета для этих пикселей.
В большинстве случаев значения альфа-смешивания каждого цветового канала одинаковы.
Таким образом, у нас есть (As, As, As, As) для исходного пикселя,
Целевые пиксели: 1, 1, 1, 1) — (As, As, As, As).
Приведенная выше формула становится следующей:
(Рс Ас + Рд (1 - Ас), Гс Ас + Гд (1 - Ас), Бс Ас + Бс (1 - Ас), Ас Ас + Ад (1 - Ас))
Эта формула обеспечивает прозрачный/полупрозрачный эффект.
Смешение цветов в OpenGL
Шаги по реализации смешивания цветов в OpenGL аналогичны процессу OpenGL, о котором мы упоминали ранее.
Затем задайте формулу и отключите кэш глубины записи при рисовании прозрачных объектов.
Потому что мы хотим нарисовать объект за полупрозрачной формой.
Это неправильный способ смешивания цветов, но в большинстве случаев он отлично работает в простых проектах.
Дополнение Руи Мартинса: Правильный процесс смешивания цветов должен заключаться в том, чтобы сначала нарисовать всю сцену, а затем нарисовать прозрачную графику.
И они рисуются в порядке, обратном буферу глубины (самые дальние объекты рисуются первыми).
Рассмотрим альфа-смешение двух полигонов (1 и 2). Разный порядок прорисовки даст разные результаты.
(Здесь предполагается, что полигон 1 находится ближе всего к наблюдателю, тогда правильный процесс должен сначала нарисовать полигон 2, а затем — полигон 1.
Как вы можете видеть в реальности,
Свет, исходящий из-за этих двух <прозрачных> полигонов, всегда сначала проходит через полигон 2.
Затем он проходит через полигон 1 и наконец достигает глаз наблюдателя. )
Когда кэширование глубины включено, вы должны сортировать прозрачную графику по глубине.
И нарисуйте эти прозрачные объекты после того, как будут нарисованы все сцены. В противном случае вы получите неправильные результаты.
Я знаю, что иногда это бывает болезненно, но это правильный способ сделать это.
Мы будем использовать код из урока 7.
Начните с добавления двух новых переменных в начале кода. Я переписал весь код для ясности.
}
Вар
h_RC: HGLRC; // Контекст рендеринга (таблица описания затенения).
h_DC: HDC // Контекст устройства (таблица описания устройства)
h_Wnd: HWND // дескриптор окна;
h_Instance: HINST // Экземпляр программы (экземпляр).
клавиши: Array[0..255] Boolean // Массив для клавиатурных процедур;
Light : Boolean // источник света вкл/выкл;
blend : Boolean; // Смешивание ВЫКЛ/ВКЛ (новое)
lp : Boolean; // Нажата ли клавиша L?
fp : Boolean; // Нажата ли клавиша F?
bp : Boolean; // Нажата ли клавиша B (Новая)?
xrot : GLfloat // вращение по оси X;
yrot: GLfloat // вращение по оси Y;
xspeed : GLfloat // скорость вращения по оси X;
yspeed : GLfloat // скорость вращения по оси Y;
z : GLfloat = -5.0 f // Расстояние вглубь экрана
LightAmbient: Array[0..3] Of GLfloat = (0.5, 0.5, 0.5, 1.0 //Параметры окружающего освещения (новое)
LightDiffuse: Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0 // Параметры рассеянного света (новое);
LightPosition: Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0 // Положение источника света (новое);
фильтр: GLUint; // Тип фильтра;
текстура: Array[0..2] Of GLuint // Место для хранения 3 текстур;
PROcedure glGenTextures (n: GLsizei; Var текстуры: GLuint external);
opengl32;
Процедура glBindTexture (цель: GLenum; текстура: GLuint);
opengl32;
Функция gluBuild2DMipmaps (цель: GLenum; компоненты, ширина, высота: GLint;
формат, тип: GLenum; данные: указатель): целое число; внешнее имя glu32;
'gluBuild2DMipmaps';
{
Затем перейдите к LoadGLTextures().
Найти, если (TextureImage[0]=LoadBMP('Data/Crate.bmp'))
Эта линия. Теперь мы используем текстуру тонированного стекла вместо текстуры деревянного ящика из предыдущего урока.
if (TextureImage[0]=LoadBMP("Data/glass.bmp")); // Загрузить растровое изображение стекла (измененное));
}
Функция LoadTexture: boolean; //Загружаем растровое изображение и преобразуем его в текстуру.
Вар
Статус: логическое значение // Индикатор состояния;
TextureImage : Array[0..1] Of PTAUX_RGBImageRec // Создаём место для хранения текстур;
Начинать
Статус: = ложь;
ZeroMemory(@TextureImage, sizeof(TextureImage)); // Устанавливаем указатель в NULL
TextImage[0] := LoadBMP('Walls.bmp');
Если TextImage[0] <> Nil Тогда
Начинать
Статус := ИСТИНА // Установить статус ИСТИНА;
glGenTextures(1, текстура[0]); // Создаем текстуру
// Создать карту ближайшего фильтра
glBindTexture (GL_TEXTURE_2D, текстура [0]);
// Генерируем текстуру
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // (новое)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // (новое)
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
Текстурное изображение[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
ТекстурноеИзображение[0].data);
glBindTexture(GL_TEXTURE_2D,texture[1]); //Используем типичную текстуру, сгенерированную из растровых данных
// Генерируем текстуру
glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
Текстурное изображение[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
ТекстурноеИзображение[0].data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Линейная фильтрация;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Линейная фильтрация;
//Создаем текстуру MipMapped
glBindTexture(GL_TEXTURE_2D, текстура[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST); // (новый)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0].sizeX,
TextureImage[0].sizey, GL_RGB, GL_UNSIGNED_BYTE,
TextImage[0].data); //(новый) }
Конец;
Если присвоено(TextureImage[0]) Тогда // Существует ли текстура
Если присвоено(TextureImage[0].data) Тогда // Существует ли изображение текстуры
TextureImage[0].data := Nil // Освободите память, занятую изображением текстуры;
TextureImage[0] := Nil // Освобождаем структуру изображения;
результат := Статус // Возвращаем статус;
Конец;
{
Добавьте следующие две строки в раздел кода glInit().
Первая строка рисует этот объект с полной яркостью и дает ему 50% альфа-смешение (полупрозрачный).
Когда опция смешивания включена, этот объект будет прозрачным на 50%.
Вторая строка задает тип используемого смешивания.
Добавил Руи Мартинс:
Значение альфа-канала 0,0 означает, что материал объекта полностью прозрачен.
1.0 означает полную непрозрачность.
}
Процедура glInit() // Здесь начинаются все настройки OpenGL.
Начинать
If (Not LoadTexture) then // Вызов подпрограммы загрузки текстуры
выход; // Если не удалось загрузиться, выходим
glEnable(GL_TEXTURE_2D); // Включаем наложение текстур
glShadeModel(GL_SMOOTH); // Включаем сглаживание теней;
glClearColor(0.0, 0.0, 0.0, 0.0); // черный фон;
glClearDepth(1.0); //Устанавливаем буфер глубины
glEnable(GL_DEPTH_TEST); // Включить тестирование глубины
glDepthFunc(GL_LESS); // Тип выполненной проверки глубины
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //Высокооптимизированный расчет перспективной проекции
glLightfv(GL_LIGHT1, GL_AMBIENT, @LightAmbient[0]); // Устанавливаем окружающий свет
glLightfv(GL_LIGHT1, GL_DIFFUSE, @LightDiffuse[0]); // Устанавливаем рассеянный свет
glLightfv(GL_LIGHT1, GL_POSITION, @LightPosition); // Положение источника света;
glEnable(GL_LIGHT1); // Включаем источник света №1;
glColor4f(1.0, 1.0, 1.0, 0.5 // Полная яркость, 50% альфа-смешивание (новое);
glBlendFunc(GL_SRC_ALPHA, GL_ONE // Функция полупрозрачного смешивания на основе значения альфа-канала исходного пикселя (новое)
Конец;
{Найдите следующий фрагмент кода в конце урока 7.
Ifkeys[VK_LEFT] Тогда //Нажата ли клавиша направления влево?
yspeed := yspeed - 0.01 //Если да, уменьшите yspeed;
После приведенного выше кода мы добавляем следующий код.
Эти строки отслеживают, нажата ли клавиша B.
Если да, компьютер проверяет, включена ли опция смешивания.
Затем установите его в противоположное состояние.
}
If (keys[ord('B')] And Not bp) Тогда //Клавиша B нажата, а bp имеет значение ЛОЖЬ?
Начинать
bp := TRUE // Если да, bp устанавливается в TRUE;
blend := Не смешивать // Переключить параметры смешивания на TRUE/FALSE;
If (смешать) Тогда // Смешение включено?
Начинать
glEnable(GL_BLEND); // Включаем смешивание
glDisable(GL_DEPTH_TEST); // Выключаем проверку глубины
Конец
Еще // еще
Начинать
glDisable(GL_BLEND); // выключаем смешивание
glEnable(GL_DEPTH_TEST); // Включаем тест глубины
Конец;
Конец;
If (Notkeys[ord('B')]) Тогда // Отпущена ли клавиша B?
Начинать
bp := FALSE // Если да, установите bp в FALSE;
Конец;
{
Но как указать цвет перехода при использовании наложения текстур? Это очень просто.
При настройке режима текстуры цвет каждого пикселя текстурной текстуры определяется параметром альфа-канала.
Получается путем умножения текущего цвета пикселя.
Например, нарисованный цвет (0,5, 0,6, 0,4),
Мы перемножим цвета, чтобы получить (0,5, 0,6, 0,4, 0,2)
(Если параметр альфа не указан, по умолчанию он равен нулю).
Вот и все! Реализация альфа-смешивания в OpenGL действительно очень проста!
}
{
Исходная заметка (13.11.99)
Мой код смешивания цветов (NeHe) был изменен, чтобы отображаемые объекты выглядели более реалистично.
Использование параметра альфа для одновременного смешивания исходных пикселей и пикселей назначения приведет к тому, что искусственные следы объекта будут выглядеть очевидными.
Это сделает заднюю часть объекта по бокам темнее.
По сути, объект будет выглядеть странно.
Метод смешивания цветов, который я использовал, возможно, не самый лучший, но он работает.
При включенном освещении объекты выглядят реалистично.
Спасибо Тому за предоставленный исходный код. Метод смешивания цветов, который он использовал, правильный.
Но объект выглядит не так привлекательно, как ожидалось :)
Код был снова изменен для устранения проблем с функцией glDepthMask() на некоторых видеокартах.
Эта команда кажется не очень эффективной при включении или отключении тестирования буфера глубины на некоторых картах.
Поэтому я преобразовал код для включения или отключения проверки буфера глубины в старомодные glEnable и glDisable.
Альфа-смешивание текстурных карт.
Параметр альфа, используемый для карты текстуры, можно прочитать из карты проблем так же, как и цвет.
Способ заключается в следующем: вам необходимо загрузить необходимый материал и одновременно получить его альфа-параметр.
Затем используйте цветовой формат GL_RGBA при вызове glTexImage2D().
}