Я написал программу трассировки лучей, которая (на данный момент) имеет два варианта для поверхностного освещения: окружающего и отражающего. Окружающее освещение воспроизводит, как естественные поверхности рассеивают свет. Отражения, очевидно, воспроизводят, как зеркала отражают свет. Все работает нормально, но я не могу понять, как смешивать цвета с глянцевыми отражениями.Java: Ray Tracing: раскраска с глянцевым отражением
Алгоритм отражения возвращает цвет и работает рекурсивно. Лучи «отлиты» в виде параметризованных линий. Когда они попадают на отражающую поверхность, они отлично отскакивают (и мои методы для этой работы). Затем эти отраженные лучи используются в качестве параметров для повторного вызова алгоритма отражения. Это продолжается до тех пор, пока текущий луч не попадет на окружающую (не отражающую) поверхность, или текущий луч вообще не ударит по поверхности.
То, как я сейчас вычисляю цвета, я усредняю цвета отраженной поверхности и вновь попавшей поверхности назад. Так что цвета на поверхностях, которые луч поражает на ранней стадии, представлены более чем более поздними поверхностными цветами.
Если цвет A - это цвет первой (отражающей) поверхности, на которую он попадает, цвет B - это цвет второй поверхности, на которую он попадает, C - третья и т. Д. Таким образом, в конечном цвете возвращается 50% A, 25% B, 12,5% C ...
Метод, который я использую для этого, фактически поддерживает средневзвешенное значение, так что зеркальные поверхности оказывают меньшее влияние на конечный цвет. Вот он:
public void addColor(Color b, double dimFac) {
double red = c.getRed() * (1 - dimFac) + b.getRed() * dimFac;
double green = c.getGreen() * (1 - dimFac) + b.getGreen() * dimFac;
double blue = c.getBlue() * (1 - dimFac) + b.getBlue() * dimFac;
c = new Color((int) red,
(int) green,
(int) blue);
}
Вот скриншот программы с этим. Есть три окружающие сферы нависают над глянцевой отражающей плоскости, С «dimFac» 0.5:
Вот та же модель с dimFac 1 так, что зеркало не имеет никакого влияния на конечный цвет:
Здесь dimFac составляет 0,8
А вот это 0,1
Может быть, это только мне, но ни один из этих отражений выглядят удивительно реалистично. То, что я использую в качестве руководства, - это powerpoint от Cornell, который, между прочим, упоминает что-либо о добавлении цветов. Зеркала имеют цвет в определенной степени, и я не знаю правильного способа смешивания цветов. Что я делаю что-то неправильно?
Таким образом, я получаю цвет от луча следующим образом. Каждая итерация лучей начинается с начала фигур. Эта программа поддерживает три формы: плоскости, сферы и прямоугольные призмы (в конечном итоге это всего лишь 6 самолетов). У меня есть класс для каждой фигуры и класс (называемый Shapes), который может хранить каждый тип фигуры (но только один объект).
После того, как формы были сделаны, класс (называемый проектором) отбрасывает лучи через другой класс под названием MasterLight (который фактически содержит методы отслеживания основных лучей, тени, отражения и (сейчас) преломления).
Чтобы получить цвет пересечения, я вызываю метод getColor(), который принимает вектор (как я хранил 3D-точки) пересечения.Я использую это для определения незаштрихованного цвета поверхности. Если поверхность нетекстурирована и имеет только пустой цвет (например, фигуры выше), то возвращается несимметричный цвет (это просто сохраняется в каждом из классов формы «Цвет c = Цвет.RED»). Например, Color.RED
Я принимаю этот цвет и рекурсивно подключаю его обратно в MasterLight в качестве базового цвета, чтобы получить затенение, как если бы поверхность была нормальной и окружающей. Этот процесс возвращает оттенок, который обычно имеет форма. Теперь значение RGB может быть (128, 0, 0);
public Color getColor(Vector v) {
if (texturing) {
return texturingAlgorithm;
}
else {
return c;
}
}
DimFac способ, которым он используется, имеет потенциал быть чем угодно от 0 до 1; В моей программе сейчас 0,8 (что является универсальной константой затенения). При окружающем затенении я принимаю значение, что я уменьшаю цвет и умножаю его на 0,8 и добавляю 0,2 (1 - 0,8), так что dimmest a цвет может быть в 0,2 от его первоначальной яркости).
AddColor находится в другом классе (у меня есть 17 на данный момент, один из которых представляет собой перечисление), называемый пересечением. В нем хранится вся важная информация о пересечениях лучей с фигурами (цвет, положение, нормальный вектор поверхности удара и другая константа, относящаяся к материалу объекта). Цвет c - текущий цвет в этой точке вычислений.
Каждая итерация отражений вызывает addColor с самым последним цветом поверхности. Чтобы уточнить, если (на картинке выше) луч только что отскочил от самолета и ударил сферу и отскочил в пустое пространство, я сначала нахожу цвет поверхности сферы в точке отскока, что и есть 'установлен в. Затем я вызываю addColor с цветом плоскости в точке пересечения (в первый раз).
Как только я вернусь отследить все отражения, я остался с цветом, который я использую, чтобы покрасить пиксель этого конкретного луча.
Сообщите, если я пропустил что-либо или было неясно.
Можете ли вы предоставить копию метода, который вы используете, чтобы получить цвет для луча? Кроме того, можете ли вы предоставить некоторый контекст вокруг вашего метода 'addColor()': является ли атрибут 'dimFac' для каждого объекта, как в материале? Или это глобальная ценность? Можете ли вы объяснить, как вы используете 'Цвет'' c'? –