現(xiàn)代OpenGL學(xué)習(xí)-07

原文地址

環(huán)境光(固有色)

The ambient component of the Phong reflection model basically specifies a minimum brightness. Even if there is no light hitting a surface directly, the ambient component will light up the surface a little bit to stop it from being pure black. The ambient brightness is constant for all surfaces.

We will calculate the ambient component using a percentage of the original intensities of the light source. We will store this ambient percentage as a float with a value between zero (0%) and one (100%), in a variable named ambientCoefficient. For example if ambientCoefficient is 0.05 (5%) and the reflected light intensities are (1,0,0)

, which is pure red light, then the ambient component will be (0.05,0,0)

, which is very dim red light.

vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities;

The specular component is what makes a surface look shiny. The word "specular" means "like a mirror," and it is used here because the shiny patches (a.k.a. specular highlights) are fake reflections of light, like a mirror would reflect light.


R is new, and it represents the angle of reflection (AoR).


Notice how when the topcoat reflects light, the rays don't hit the paint layer. Normally the paint layer would change the color of the light by absorbing some of the intensities, but that can't happen if the light doesn't hit the paint. This means that the specular component is usually a different color to the diffuse component. Most specular surfaces don't absorb anything, they just reflect all of the light, which means the specular color would be white. This is why the shiny parts of a car are white, even though the paint is red.


To apply the specular exponent, we take cos(angle) and raise it to the power of the specular exponent. This produces the "specular coefficient", which is the brightness of the reflection.

vec3 incidenceVector = -surfaceToLight; //a unit vector

vec3 reflectionVector = reflect(incidenceVector, normal); //also a unit vector

vec3 surfaceToCamera = normalize(cameraPosition - surfacePosition); //also a unit vector

float cosAngle = max(0.0, dot(surfaceToCamera, reflectionVector));

float specularCoefficient = pow(cosAngle, materialShininess);

vec3 specularComponent = specularCoefficient * materialSpecularColor * light.intensities;

光線距離衰減

float attenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));

The GLSL to combine the ambient, diffuse and specular components, including attenuation, looks like this:

vec3 linearColor = ambient + attenuation*(diffuse + specular);

This is almost the final color for the fragment/pixel. The last step is to do gamma correction.

之前的顏色計算是在線性顏色空間計算的

For example, the 100% red color (1,0,0)

should be twice as bright as the 50% red color (0.5,0,0)

.

但是顯示器的顏色空間不是線性的楔壤;


The 100% red is actually about 4.5 times brighter than the 50% red, which makes the brightness in the 3D scene look wrong.

Gamma correction is pretty simple to implement. You take each of the RGB values and raise them to the power of gamma. Some games give the user a brightness setting which allows them to change the gamma value, but we will just use the constant value 1/2.2

in this article, which is the correct value for CRT monitors.

vec3 gamma = vec3(1.0/2.2);

finalColor = pow(linearColor, gamma);

vec3 gamma = vec3(1.0/2.2, 1.0/2.2, 1.0/2.2);

finalColor = vec3(pow(linearColor.r, gamma.r),

pow(linearColor.g, gamma.g),

pow(linearColor.b, gamma.b));

#version 150

uniform mat4 model;

uniform vec3 cameraPosition;

// material settings

uniform sampler2D materialTex;

uniform float materialShininess;

uniform vec3 materialSpecularColor;

uniform struct Light {

vec3 position;

vec3 intensities; //a.k.a the color of the light

float attenuation;

float ambientCoefficient;

} light;

in vec2 fragTexCoord;

in vec3 fragNormal;

in vec3 fragVert;

out vec4 finalColor;

void main() {

vec3 normal = normalize(transpose(inverse(mat3(model))) * fragNormal);

vec3 surfacePos = vec3(model * vec4(fragVert, 1));

vec4 surfaceColor = texture(materialTex, fragTexCoord);

vec3 surfaceToLight = normalize(light.position - surfacePos);

vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);

//ambient

vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities;

//diffuse

float diffuseCoefficient = max(0.0, dot(normal, surfaceToLight));

vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities;

//specular

float specularCoefficient = 0.0;

if(diffuseCoefficient > 0.0)

specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), materialShininess);

vec3 specular = specularCoefficient * materialSpecularColor * light.intensities;

//attenuation

float distanceToLight = length(light.position - surfacePos);

float attenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));

//linear color (color before gamma correction)

vec3 linearColor = ambient + attenuation*(diffuse + specular);

//final color (after gamma correction)

vec3 gamma = vec3(1.0/2.2);

finalColor = vec4(pow(linearColor, gamma), surfaceColor.a);

}

There are new material uniforms:

uniform sampler2D materialTex;

uniform float materialShininess;

uniform vec3 materialSpecularColor;


struct ModelAsset {

tdogl::Program* shaders;

tdogl::Texture* texture;

GLuint vbo;

GLuint vao;

GLenum drawType;

GLint drawStart;

GLint drawCount;

GLfloat shininess; //new this article

glm::vec3 specularColor; //new this article

};

struct Light {

glm::vec3 position;

glm::vec3 intensities;

float attenuation; //new this article

float ambientCoefficient; //new this article

};

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市巴帮,隨后出現(xiàn)的幾起案子趁窃,更是在濱河造成了極大的恐慌,老刑警劉巖剖淀,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件味廊,死亡現(xiàn)場離奇詭異,居然都是意外死亡骂铁,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門罩抗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來拉庵,“玉大人,你說我怎么就攤上這事套蒂〕В” “怎么了茫蛹?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長烁挟。 經(jīng)常有香客問我婴洼,道長,這世上最難降的妖魔是什么撼嗓? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任柬采,我火速辦了婚禮,結(jié)果婚禮上且警,老公的妹妹穿的比我還像新娘粉捻。我一直安慰自己,他們只是感情好斑芜,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布肩刃。 她就那樣靜靜地躺著,像睡著了一般杏头。 火紅的嫁衣襯著肌膚如雪盈包。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天醇王,我揣著相機與錄音呢燥,去河邊找鬼。 笑死厦画,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的滥朱。 我是一名探鬼主播根暑,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼徙邻!你這毒婦竟也來了排嫌?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤缰犁,失蹤者是張志新(化名)和其女友劉穎淳地,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帅容,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡颇象,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了并徘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片遣钳。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖麦乞,靈堂內(nèi)的尸體忽然破棺而出蕴茴,到底是詐尸還是另有隱情劝评,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布倦淀,位于F島的核電站蒋畜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏撞叽。R本人自食惡果不足惜姻成,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望能扒。 院中可真熱鬧佣渴,春花似錦、人聲如沸初斑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽见秤。三九已至砂竖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鹃答,已是汗流浹背乎澄。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留测摔,地道東北人置济。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像锋八,于是被迫代替她去往敵國和親浙于。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容