Подсветка Blinn-Phong — лучший расчет полного цвета

Почти все статьи и книги, которые я прочитал, утверждают, что композиция окончательного цвета:
finalColor = ambientColor + lambertianTerm * diffuseColor (= цвет материала) + specularIntensity * specularColor (= светлый цвет)

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 6th edition -> Rendering Techniques -> Lighting Models -> Blinn-Phong Lighting, Wikipedia -> модель затенения Блинна-Фонга (см. Фрагментный шейдер), и другие.

Существует проблема в расчете конечного цвета: цвет света (также рассмотрим случай с несколькими источниками света) не участвует в формулировке рассеянного цвета. Рассмотрим случай, когда коэффициент блеска велик — скажем, 128,0, так что зеркальное пятно мало и большая часть площади объекта окрашена с использованием диффузного члена. Также позвольте цвету объекта быть зеленым и свету — красным. Результатом вышеприведенного уравнения, если нет окружающего цвета, является частично освещенный чисто зеленый объект с небольшим желтым пятном на нем = зеленый + красный = свет от красного источника света, отраженный от зеленого объекта:
чисто зеленый диффузный цвет + желтая зеркальная подсветка
Это не правильно. Конечно, зеленый + красный — желтый, но наверняка вы не увидите ни чисто зеленого шара, ни желтого зеркального пятна. Держите в руке зеленый блестящий шар — например, большую шестерку из бильярдной игры, а затем зажгите его красным светом — я могу заверить вас, что вы не увидите только зеленый рассеянный и желтый зеркальный. Вместо этого вы увидите смешанный зеленый + красный для размытого и более красного зеркального пятна. Лучший способ, который я нашел на данный момент, чтобы вычислить окончательный цвет — среднее смешивание:

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 );

… или нелинейным способом, о котором я не могу думать.

Итак, последний вопрос: каков лучший расчет полного цвета?
Кроме того, скажите мне, если я что-то упускаю, но, по моему мнению, чисто зеленая картинка + чисто желтая зеркальная подсветка совершенно не сценарий реального мира.

0

Решение

Цветовой смысл поверхности — это «какие цвета света могут быть диффузный с этой поверхности «.

Цветовой смысл означает, что цвета света могут быть отраженный с этой поверхности «.

Светлый цвет означает «что цвета света достигают поверхности».

Таким образом, вы должны умножить их:

   finalColor = ambient
+ lambertianTerm * surfaceColor * lightColor
+ specularIntensity * specularColor * lightColor;
1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]