Почти все прочитанные статьи и книги гласят, что состав окончательного цвета: finalColor = ambientColor + lambertianTerm * diffuseColor (= материал цвет) + specularIntensity * specularColor (= светлый цвет)Подсветка Blinn-Phong - наилучший расчет полного цвета
lambertianTerm = dot(surfaceNormal, normalize(lightPos - surfacePos));
halfVector = normalize(normalize(lightPos - surfacePos) + normalize(eyePos - surfacePos);
specularFactor = max(dot(halfVector, surfaceNormal), 0.0f);
specularIntensity = pow(specularFactor, surfaceShininessLevel);
Вот некоторые из мест, которые используют вышеупомянутый подход для вычисления окончательного цвета: OpenGL SuperBible шестого издания -> Rendering Techniques -> Освещение Models -> Blinn -Phong Lighting, Wikipedia -> Blinn–Phong shading model (see the fragment shader) и другие.
Существует проблема при вычислении конечного цвета: цвет света (также учитывающий случай с несколькими источниками света) не участвует в формулировке диффузного цвета. Рассмотрим случай, когда коэффициент блеска является большим числом - 128,0, скажем так, чтобы зеркальное пятно было небольшим, и большая часть области объекта была окрашена с использованием диффузного термина. Также пусть цвет объекта будет зеленым, а свет - красным. Вывод уравнения выше, если нет окружающего цвета, является частично освещенным чисто зеленым объектом с небольшим желтым пятном на нем = зеленый + красный = свет от источника красного света, отраженного от зеленого объекта: Это не верный. Конечно, зеленый + красный желтый, но наверняка вы не увидите ни зеленого шара, ни желтого зеркального пятна. Возьмите зеленый блестящий шар в руке - например, большой 6 из бильярдной игры, а затем зажгите его красным светом - я мог бы заверить вас, что вы не увидите только зеленого рассеянного и желтого зеркального. Вместо этого вы увидите смешанный зеленый + красный цвет для рассеянного и более красного пятна. Лучший способ я нашел до сих пор, чтобы вычислить окончательный цвет - среднее смешивания:
finalColor = ambient
+ lambertianTerm * (surfaceColor + lightColor)/2.0
+ specularIntensity * lightColor;
Пробовал наложения смешивания:
const vec4 srgbLuminanceFactor = vec4(0.2125f, 0.7154f, 0.0721f, 1.0f);
vec4 overlay(vec4 baseColor, vec4 blendColor)
{
float luminance = dot(baseColor, srgbLuminanceFactor);
vec4 lowerLumOverlay = 2.0f * blendColor * baseColor;
if (luminance < 0.45f)
{
return lowerLumOverlay;
}
const vec4 whiteColor = vec4(1.0);
vec4 higherLumOverlay = whiteColor - 2.0f * (whiteColor - blendColor) * (whiteColor - baseColor);
return luminance > 0.55f
? higherLumOverlay
: mix(lowerLumOverlay, higherLumOverlay, (luminance - 0.45f) * 10.0f);
}
... но не выглядит хорошо. Возможно, свет и цвет объекта должны быть смешаны в другом линейном соотношении:
mix(surfaceColor, lightColor, ratio);
... или нелинейным способом, который я не могу думать.
Итак, последний вопрос: какой лучший расчет полного цвета? Кроме того, скажите мне, если я что-то упустил, но, на мой взгляд, чистая зеленая картинка + чисто желтая зеркальная подсветка полностью не сценарий реального мира.