2016-06-13 5 views
1

Я написал программу трассировки лучей, которая (на данный момент) имеет два варианта для поверхностного освещения: окружающего и отражающего. Окружающее освещение воспроизводит, как естественные поверхности рассеивают свет. Отражения, очевидно, воспроизводят, как зеркала отражают свет. Все работает нормально, но я не могу понять, как смешивать цвета с глянцевыми отражениями.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:

enter image description here

Вот та же модель с dimFac 1 так, что зеркало не имеет никакого влияния на конечный цвет:

enter image description here

Здесь dimFac составляет 0,8

enter image description here

А вот это 0,1

enter image description here

Может быть, это только мне, но ни один из этих отражений выглядят удивительно реалистично. То, что я использую в качестве руководства, - это 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 с цветом плоскости в точке пересечения (в первый раз).

Как только я вернусь отследить все отражения, я остался с цветом, который я использую, чтобы покрасить пиксель этого конкретного луча.

Сообщите, если я пропустил что-либо или было неясно.

+0

Можете ли вы предоставить копию метода, который вы используете, чтобы получить цвет для луча? Кроме того, можете ли вы предоставить некоторый контекст вокруг вашего метода 'addColor()': является ли атрибут 'dimFac' для каждого объекта, как в материале? Или это глобальная ценность? Можете ли вы объяснить, как вы используете 'Цвет'' c'? –

ответ

3

Вы должны использовать метод Phong Shading, созданный Phong-Bui Tong в 1975 году. Уравнение Фонга упрощает освещение на три компонента: эмбиентный, диффузный и зеркальный.

Окружающий свет - это освещение вашего объекта, когда он находится в полной темноте. Источники света не влияют на освещение окружающей среды.

Диффузный свет - это яркость света, основанная на угле между нормальностью поверхности пересечения и световым вектором от пересечения.

Яркий свет - это то, что, я считаю, вы ищете. Он основан на углу между вектором от угла пересечения к положению камеры и вектором отражения для светового вектора относительно поверхности.

Вот как я обычно использую Фонг заливку:

  • Для любых объектов на сцене, определить три константы: Ka (окружающее освещение), Kd (рассеянный свет) и Ks (зеркальное освещение). Мы также определим константу «n» для блеска вашего объекта. Я бы сохранил это значение выше 3.
  • Найти точечный продукт нормального вектора и вектора света, назовем это количество «dF» пока.
  • Теперь давайте вычислим вектор отражения: это нормальный вектор, умноженный на точечное произведение нормального вектора и вектора света, умноженное на два. Вычтите вектор света, и это должно иметь величину 1, если бы выполнялись нормальные и световые векторы.
  • Найти точечный продукт вектора отражения и вектор для зрителя с пересечения, назовем это «sF».
  • Наконец, мы назовем цвет вашего объекта «clr», а окончательный цвет будет называться «fClr».
  • Чтобы получить окончательный цвет, используйте формулу: fClr = Ka (CLR) + Kd (коэффициент) (CLR) + Кз (specularFactor^п) (CLR)
  • Наконец, я проверяю, если любой из ваших R , G или B находятся за пределами границ. Если это так, сделайте это значение R, G или B равным ближайшей границе.

** Выполните уравнение для каждого значения RGB, если вы используете RGB.

** Я хотел бы отметить, что все значения RGB должны быть скалярами 0,0 - 1,0. Если вы используете 8-битный RGB (0-255), разделите значения на 255, прежде чем вводить их в уравнение, и умножьте выходные значения на 255.

** Каждый раз, когда я обращаюсь к вектору, он должен быть единичным вектором, то есть он должен иметь величину 1.

Надеюсь, это поможет! Удачи!