2016-10-06 15 views
0

Я работаю над лучей с использованием C++ и OpenGL (glDrawPixels), и пока все идет хорошо. Тем не менее, моя затенение, похоже, немного выключена. Я хочу, чтобы мои сферы выглядели немного более гладкими, не имея вопиющих линий между интенсивностями. На данный момент я просто пытаюсь реализовать ламбертовское затенение, которое является Intensity = Id * pd * (N точка L). Я знаю, как мне нужно вычислить (N точка L), нормализуя вектор вектора вектора и света, но как насчет Id и pd (интенсивность диффузии и коэффициент пропорциональности)? Я только с помощью постоянного значения 2,5 для достижения следующих:Как реализовать ламбертовское затенение

(Here is a picture of what my shading looks like)

Очевидно, что 2,5 совершенно произвольно, и я только использовать его, потому что другие мои попытки даже не похожи на надлежащее затенение. Вышеприведенное уравнение, по-видимому, предполагает, что я должен умножить цвет на интенсивность. Это мой метод:

Color simpleIlluminate(Vector3D normal, Vector3D light, Color color) { 
    float intensity = dotProduct(normal, light)*2.5f; 
    color = Color((unsigned int)intensity*color.r, (unsigned int)intensity*color.g, (unsigned int)intensity*color.b); 
    return color; 
} 

Предположим, что нормальный вектор и вектор света верны. Цвет - это только цветная структура, которую я создал, которая имеет unsigned int для каждого из значений RGB. Параметр Color color - цвет сферы, которую я хочу затенять, например. красный = цвет (255,0,0). Чтобы изменить интенсивность цвета, я просто умножаю каждое значение на рассчитанную интенсивность, но при запуске я не выгляжу правильно.

Может кто-нибудь объяснить, что мне не хватает, и показать мне, как должна выглядеть правильная функция, учитывая данные о векторах и сфере сферы? Я везде искал, но я не могу найти хорошее решение. Возможно, я также ошибаюсь в том, что мой float для неподписанного преобразования int ошибочен, но я не уверен. Любая помощь приветствуется.

+0

Возможно, вам придется исправить гамму. Масштабируйте значения RGB с силой 2,2. Вычисленная интенсивность является линейной, но значения RGB настраиваются так называемым «гамма». Проверьте sRGB в wiki. Кроме того, убедитесь, что самые яркие значения RGB поверхности меньше 255, или они будут зажиматься. – doug

ответ

1

Я хотел бы удалить этот 2.5-фактор, как это, вероятно, завинчивание с результатами, и это очень хорошо может производить полосатость, так как вы расширения коэффициента за пределы диапазона от 0 до 1.

Ламберта отражательной также известно как отражение косинуса, и на самом деле просто понять. Рассмотрим плоскость, если свет перпендикулярен плоскости, тогда весь свет упадет на поверхность (100% или коэффициент 1,0). Если бы свет указывал параллельно этой плоскости, тогда на поверхности света падал бы свет 0 (все лучи света параллельны и, следовательно, никогда не пересекают плоскость, поэтому коэффициент или 0).

Ламбертовский коэффициент отражения - это просто косинус угла между направлением света и нормальностью поверхности и находится в диапазоне от 0 (без света, попадающего в плоскость) до 1,0 (весь свет попадает в плоскость). Примечание. Косинус (90) = 1. Косинус (0) = 0, поэтому называется косинус-законом (ламбертовская отражательная способность).

0

я также мог бы делать мой поплавок для неподписанных Int преобразования неверного

пятна на. (unsigned int)intensity*color.r эквивалентен ((unsigned int)intensity)*color.r. Таким образом, ваша интенсивность берет дискретные уровни перед тем, как их умножить на цвет, что приводит к этим линиям. Вместо этого попробуйте (unsigned int)(intensity*color.r).