Form v - - ray.dir: // direction to viewer // направление на наблюдателя
v.normalize():
Shape* myObj - (Shape*)h.hitObject; // point to the hit object // указатель на объект соударения
Color3 color(myObj->mtrl.emissive)* : //start with emissive part // начинаем с эмиссионной части
color.add(d/7!D7'ent contribution): II compute ambient color // вычисляем фоновый цвет
Vector3 normal; // transform the generic normal to the world normal // преобразуем нормаль из базовых координат в мировые
xfrmNormal(normal. myObj->invTransf. h.hitNormal);
normal, norma lizeO: // normalize it // нормируем ее
for(each light source. L) // sum over all sources // суммируем все источники
if(isInShadow(…)) continue: // skip L if it's in shadow // пропускаем точку L. если она в тени
Form s - L.pos - hitPoint: // vector from hit point to source // вектор от точки соударения до источника
s.normalizeO:
float mDotS - s.dot(normal); // the Lambert term // член Ламберта
if(mDotS > 0.0) // hit point is turned toward the light // точка соударения повернута к свету
Form diffuseColor = mDotS * myObj->mtrl.diffuse * L.color; color.add(diffuseColor): // add the diffuse part
Предполагается, что к классам УесЬогЗ и СоТогЗ добавлены некоторые удобные конструкторы: УесЬогЗ 5(А, В) вычисляет вектор как разность двух точек А и В, а СоТогЗ со1ог(с) создает цвет, имеющий те же компоненты, что и цвет с.
Введение в трассировку лучей
Листинг 14.10 (продолжение)
// добавляем диффузную часть
Form h = v + s: // the halfway vector // промежуточный вектор
h.normalizeO:
float mDotH - h.dot(normal): // part of phong term // часть члена Фонга
if (mDotH <- 0) continue: // no specular contribution // зеркального отражения нет
float phong = pow(mDotH. myObj->mtrl.specularExponent):
specColor - phong * myObj->mtrl.specular * L.col or:
color.add(specColor):
}
return color:
}
Нетрудно добавить в трассировщик луча вычисления фоновой, диффузной и зеркальной составляющих света. В листинге 14.10 показан скелет кода, который требуется добавить в метод shadeO из листинга 14.4. Запись наилучшего пересечения best, формируемая в подпрограмме getFirstHitO, исследуется с целью сбора данных о первом соударении луча с объектом. Копию best. hit[0] удобно помещать в Hitinfo, запись п. Положение точки соударения hitPoint вычисляется при помощи луча и h.hitTime. Нормаль в точке соударения, хранящаяся в h.hitNormal в базовых координатах, преобразуется с помощью уравнения (14.24) в мировые координаты. Различные составляющие суммарного цвета, возвращающиеся обратно по лучу, вычисляются и помещаются в color. Определяются эмиссионная и фоновая составляющие света и для каждого источника света исходящие из него диффузная и зеркальная составляющие; все они вычисляются и добавляются ко все растущему color. Если в точке соударения на данный источник света падает тень от другого объекта, то от такого источника не добавляется ничего. (Мы будем рассматривать тени в разделе «Добавление теней для большей реалистичности»; пока же просто опустим строку кода