2015-11-08 2 views
0

Почти все прочитанные статьи и книги гласят, что состав окончательного цвета: 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, скажем так, чтобы зеркальное пятно было небольшим, и большая часть области объекта была окрашена с использованием диффузного термина. Также пусть цвет объекта будет зеленым, а свет - красным. Вывод уравнения выше, если нет окружающего цвета, является частично освещенным чисто зеленым объектом с небольшим желтым пятном на нем = зеленый + красный = свет от источника красного света, отраженного от зеленого объекта: purely green diffuse color + yellow specular highlight Это не верный. Конечно, зеленый + красный желтый, но наверняка вы не увидите ни зеленого шара, ни желтого зеркального пятна. Возьмите зеленый блестящий шар в руке - например, большой 6 из бильярдной игры, а затем зажгите его красным светом - я мог бы заверить вас, что вы не увидите только зеленого рассеянного и желтого зеркального. Вместо этого вы увидите смешанный зеленый + красный цвет для рассеянного и более красного пятна. Лучший способ я нашел до сих пор, чтобы вычислить окончательный цвет - среднее смешивания:

finalColor = ambient 
      + lambertianTerm * (surfaceColor + lightColor)/2.0 
      + specularIntensity * lightColor; 

diffuse = yellow with a red accent, specular spot = almost purely red Пробовал наложения смешивания:

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

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

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

ответ

1

Поверхностный цвет означает «какие цвета света могут быть рассеянным с этой поверхности».

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

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

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

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