Метод Light в OpenGL регулирует параметры источников света
///
/// Устанавливает параметры источника света.
///
///
/// Номер источника света. Допустимы значения LIGHT0+i.
/// Максимальное значение i-1 определяется функцией Get с параметром MAX_LIGHTS.
///
///
/// Определяет параметр источника света. Допустимы значения:
/// AMBIENT - компонента окружения источника (по умолчанию (0, 0, 0, 1)),
/// DIFFUSE - компонента диффузного отражения источника
/// (по умолчанию для источника 0 (1, 1, 1, 1), для других (0, 0, 0, 1)),
/// SPECULAR - компонента зеркального отражения источника
/// (по умолчанию для источника 0 (1, 1, 1, 1), для других (0, 0, 0, 1)),
/// POSITION - положение источника света в объектных координатах
/// (по умолчанию (0, 0, 1, 0)),
/// SPOT_DIRECTION - направление луча источника (по умолчанию (0,0,-1)),
/// SPOT_EXPONENT – степень рассеяния луча света (по умолчанию 0),
/// SPOT_CUTOFF - угол раствора луча в градусах (по умолчанию 180),
/// CONSTANT_ATTENUATION - положительная константа затухания (по умолчанию 1),
/// LINEAR_ATTENUATION – положит. коэффициент линейного затухания (по умолчанию 0),
/// QUADRATIC_ATTENUATION – положит. коэфф. квадратичного затухания (по умолчанию 0).
///
///
/// Массив параметров. Размерность массива зависит от смысла параметра name.
///
[DllImport("OPENGL32.DLL", EntryPoint = "glLightfv")]
public static extern void Light(int light, int name, float[] parameter);
Символьная константа параметра light имеет вид
///
/// Параметр, нумерующий первый источник света.
/// Остальные источники нумеруются как LIGHT0+i.
///
public const int LIGHT0 = 0x4000;
Константа максимального числа источников света
///
/// Аргумент Get требует возврата значения 1 параметра - максимального
/// числа источников света.
///
public const int MAX_LIGHTS = 0x0D31;
Для активации источника света следует использовать метод Enable с параметром LIGHT0+i. Текущее состояние активации источника света определяется методом IsEnable или Get с тем же параметром.
Константы параметра name метода Light, относящиеся к цветам, указаны в предыдущих разделах. Оставшиеся константы имеют вид
public const int POSITION = 0x1203;
public const int SPOT_DIRECTION = 0x1204;
public const int SPOT_EXPONENT = 0x1205;
public const int SPOT_CUTOFF = 0x1206;
public const int CONSTANT_ATTENUATION = 0x1207;
public const int LINEAR_ATTENUATION = 0x1208;
public const int QUADRATIC_ATTENUATION = 0x1209;
Для определения текущих значений параметров метода Light следует использовать метод
///
/// Возвращает текущие значения параметров метода Light
///
///
/// Номер источника света в форме LIGHT0+i
///
///
/// Название параметра из числа AMBIENT, DIFFUSE, SPECULAR, POSITION,
/// SPOT_DIRECTION, SPOT_EXPONENT, SPOT_CUTOFF, CONSTANT_ATTENUATION,
/// LINEAR_ATTENUATION, QUADRATIC_ATTENUATION.
///
///
/// Массив возвращаемого значения параметра. Размер массива зависит от типа параметра.
///
[DllImport("OPENGL32.DLL", EntryPoint = "glGetLightfv")]
public static extern void GetLight(int light, int pname, float[] lparams);
При использовании источников света изображение объекта, вообще говоря, зависит от нормали в каждой точке поверхности. Поэтому во всех списках объектов перед каждой вершиной (метод Vertex) следует вызвать метод Normal с тремя параметрами, которые указывают вектор (не обязательно единичный) внешней нормали к поверхности в данной точке. Так выглядит заголовок метода Normal
///
/// Определяет вектор (nx, ny, nz) (не обязательно нормированный) направления
/// нормали в точке положения вершины.
///
[DllImport("OPENGL32.DLL", EntryPoint = "glNormal3f")]
public static extern void Normal(float nx, float ny, float nz);
Здесь дается редакция методов, создающих списки сферы, тора и усеченного конуса, описанных в классе listMaker библиотеки GL, с учетом нормализации вершин:
-
Сфера (метод Sphere):
-
При формировании северного полюса код принимает вид
gl.Normal(0, 1, 0);
gl.Vertex(0, 1, 0);
for (int slice = 0; slice <= slices; slice++)
{
gl.Normal(sinteta[1] * sinfi[slice], costeta[1], sinteta[1] * cosfi[slice]);
gl.Vertex(sinteta[1] * sinfi[slice], costeta[1], sinteta[1] * cosfi[slice]);
}
-
При формировании средней части сферы код принимает вид
for (int slice = 0; slice <= slices; slice++)
{
gl.Normal(sinteta[stack] * sinfi[slice], costeta[stack],
sinteta[stack] * cosfi[slice]);
gl.Vertex(sinteta[stack] * sinfi[slice], costeta[stack],
sinteta[stack] * cosfi[slice]);
gl.Normal(sinteta[stack + 1] * sinfi[slice], costeta[stack + 1],
sinteta[stack + 1] * cosfi[slice]);
gl.Vertex(sinteta[stack + 1] * sinfi[slice], costeta[stack + 1],
sinteta[stack + 1] * cosfi[slice]);
}
-
При формировании южного полюса
gl.Normal(0, -1, 0);
gl.Vertex(0, -1, 0);
for (int slice = slices; slice >= 0; slice--)
{
gl.Normal(sinteta[stacks - 1] * sinfi[slice], costeta[stacks - 1],
sinteta[stacks - 1] * cosfi[slice]);
gl.Vertex(sinteta[stacks - 1] * sinfi[slice], costeta[stacks - 1],
sinteta[stacks - 1] * cosfi[slice]);
}
for (int bigSlice = bigSlices; bigSlice >= 0; bigSlice--)
{
gl.Normal(cosBigFi[bigSlice] * cosSmallFi[smallSlice],
cosSmallFi[smallSlice] * sinBigFi[bigSlice], sinSmallFi[smallSlice]);
gl.Vertex(curRad * cosBigFi[bigSlice], curRad * sinBigFi[bigSlice],
smallRadius * sinSmallFi[smallSlice]);
gl.Normal(cosBigFi[bigSlice] * cosSmallFi[smallSlice + 1],
cosSmallFi[smallSlice + 1] * sinBigFi[bigSlice], sinSmallFi[smallSlice + 1]);
gl.Vertex(nextRad * cosBigFi[bigSlice], nextRad * sinBigFi[bigSlice],
smallRadius * sinSmallFi[smallSlice + 1]);
}
-
Усеченный конус (метод Frustum):
-
Добавляется локальная переменная
float zNorm = (float)Math.Cos(Math.Atan2(1, 1 - topRadius));
for (int slice = slices; slice >= 0; slice--)
{
x = curRadius * cosfi[slice]; y = curRadius * sinfi[slice];
gl.Normal(x, y, zNorm);
gl.Vertex(x, y, z);
}
-
Цикл основной поверхности конуса принимает вид
for (int slice = slices; slice >= 0; slice--)
{
x = curRadius * cosfi[slice]; y = curRadius * sinfi[slice];
xNext = radiusNext * cosfi[slice]; yNext = radiusNext * sinfi[slice];
gl.Normal(x, y, zNorm);
gl.Vertex(x, y, z);
gl.Normal(xNext, yNext, zNorm);
gl.Vertex(xNext, yNext, zNext);
}
Определение текущих значений параметров метода Normal осуществляется методом Get с параметром
///
/// Аргумент Get требует возврата значения трех параметров –
/// текущих значений аргументов метода Normal.
///
public const int CURRENT_NORMAL = 0x0B02;
Для эффективного применения метода Normal следует так же активировать режим нормализации методом Enable с параметром
///
/// Параметр активации нормализации.
/// Используется методами Get, Enable, IsEnabled и Disable.
///
public const int NORMALIZE = 0x0BA1;
Эта активация нормализует векторы нормали, если они не единичные.
Для сохранения флага NORMALIZE в стеке следует использовать метод PushAttrib с параметром ENABLE_BIT.
При включенных источниках света с учетом всех перечисленных выше параметров формула цвета каждой вершины представляет собой сумму
-
интенсивности цвета излучения материи,
-
произведения интенсивностей цветов отражения материей света среды и самого света среды и
-
вклада от каждого активного источника света.
Вклад источника света состоит из трех компонент – компоненты среды, диффузной компоненты и компоненты интенсивности зеркально отражаемого света.
-
Компонента среды является произведением интенсивностей цвета отраженного материей света среды и света среды, создаваемого данным источником.
-
Диффузная компонента является произведением интенсивностей цвета диффузного отражения материи, интенсивности цвета диффузной составляющей света источника и скалярного произведения нормали вершины с нормализованным вектором направления от вершины к источнику света.
-
Компонента зеркально отражаемого света является произведением интенсивности цвета, зеркально отраженного материей света, интенсивности цвета зеркально отражаемой составляющей источника света и скалярного произведения нормали вершины на нормализованный сумму векторов, направленных от вершины к наблюдателю и от вершины к источнику света, возведенного в степень яркости материи. Наблюдатель расположен по умолчанию в положительной бесконечности оси Z, а если параметр LIGHT_MODEL_LOCAL_VIEWER метода LightModel установлен равным единице, то наблюдатель находится в начале системы координат наблюдения.
Все три компоненты умножаются одинаково на множитель, уменьшающий интенсивность и состоящий из двух множителей:
-
Первый множитель имеет вид 1/ (K0 + K1d + K2d2), где K0, K1 и K2 – соответственно, постоянный коэффициент затухания CONSTANT_ATTENUATION , линейный LINEAR_ATTENUATION и квадратичный QUADRATIC_ATTENUATION, d – расстояние от источника света до вершины. Он равен единице, если источник света находится на бесконечности (w = 0), как по умолчанию.
-
Второй множитель зависит от направления луча света SPOT_DIRECTION, угла раствора пучка света SPOT_CUTOFF и степени рассеяния луча SPOT_EXPONENT. Он равен
-
единице, если угол раствора SPOT_CUTOFF равен 1800, как по умолчанию,
-
нулю, если скалярное произведение единичного вектора от источника света к вершине и единичного вектора направления луча SPOT_DIRECTION меньше косинуса угла раствора SPOT_CUTOFF,
-
скалярному произведению единичных векторов от источника света к вершине и направления луча SPOT_DIRECTION, возведенному в степень рассеяния луча SPOT_EXPONENT в других случаях.
Все скалярные произведения, которые оказываются отрицательными, заменяются нулями.
Альфа-компонентой результирующего цвета является альфа-компонента диффузной составляющей материи.
Читатель, самостоятельно готовящий приложение, может использовать в нем приведенные методы Light и Normal для наблюдения эффекта от включения источников света и изменения параметров этих источников на примере какого-либо объекта.
Авторское приложение позволяет наблюдать и регулировать параметры приведенных методов с помощью интерфейсных элементов управления. Комментарий к коду этой части авторского приложения можно найти по ссылке.
Проектные задания
-
Оформите освещение для часов, которые готовились в предыдущих проектных заданиях.
-
Постройте список изображения примитивной кубической ячейки кристалла с произвольным числом и размером частиц, находящихся в произвольном положении, подобную той, что изображена ниже
Тест рубежного контроля
-
Опишите параметры источников света и их значения по умолчанию.
-
Какой метод активирует источник света?
-
Какой метод возвращает текущие значения параметров источника света?
-
Что делает метод Normal?
-
Какой параметр следует использовать в методе PushAttrib с тем, чтобы сохранить состояние освещенности в стеке?
-
Опишите формулу цвета вершины при освещении.
-
Какое значение имеет альфа-компонента вершины при освещении?
Достарыңызбен бөлісу: |