光照是OpenGL ES里很重要的一部分,下面我們來學(xué)習(xí)總結(jié)一下如何計算不同的光照效果。

光照計算.png
光照基礎(chǔ)
1?環(huán)境光照
2?漫反射光照
3?鏡面光照光照特性
1?發(fā)射光:由物體自身發(fā)光
2?環(huán)境光:就是在環(huán)境中充分散射的光,而且無法分辨它的方向
3?漫反射光:光線來自某個方向,但在物體上各個方向反射
4?鏡面高光:光線來自一個特定的方向,然后在物體表面上以一個特定的方向反射出去材質(zhì)屬性
1?泛射材質(zhì)
2?漫反射材質(zhì)
3?鏡面反射材質(zhì)
4?發(fā)射材質(zhì)
-
單一光照計算
1?環(huán)境光的計算環(huán)境光 = 光源的環(huán)境光顏色*物體的材質(zhì)顏色GLSL實(shí)現(xiàn):
varying vec3 objectColor; void main() { //?至少有%10的光找到物體所有?面 float ambientStrength = 0.1; //環(huán)境光顏?色 vec3 ambient = ambientStrength * lightColor; //最終顏?色 = 環(huán)境光顏?色 * 物體顏?色 vec3 result = ambient * objectColor; gl_FragColor = vec4(result, 1.0); }2?發(fā)射光的計算
發(fā)射光 = 物體的反射材質(zhì)顏色3?漫反射光的計算
漫反射顏? = 光源的漫反射顏色 * 物體的漫發(fā)射材質(zhì)顏色 * DiffuseFactor DiffuseFactor = max(0,dot(N,L)) 漫反射因?DiffuseFactor 是光線與頂點(diǎn)法線向量的點(diǎn)積GLSL實(shí)現(xiàn):
uniform vec3 lightColor;//光源? uniform vec3 lightPo;//光源位置 uniform vec3 objectColor;//物體? uniform vec3 viewPo;//物體位置 varying vec3 outNormal;//傳入當(dāng)前頂點(diǎn)平面的法向量 //確保法線為單位向量 vec3 norm = normalize(outNormal); //頂點(diǎn)指向光源 單位向量 vec3 lightDir = normalize(lightPo - FragPo); //得到兩向量的cos值 ?于0則為0 float diff = max(dot(norm, lightDir),0.0); //得到漫反射收的光源向量 vec3 diffuse = diff * lightColor; vec3 result = diffuse * ojbectColor; gl_FragColor = vec4(result,1.0);4?鏡面光的計算
鏡面反射顏色 = 光源的鏡面光的顏色 * 物體的鏡面材質(zhì)顏色 * SpecularFactor SpecularFactor = power(max(0,dot(N,H)),shininess) H :視線向量E與光線向量L的半向量 dot(N,H):H,N的點(diǎn)積幾何意義,反射光線與法線夾角的cos值 shiniess : 高光的反光度GLSL實(shí)現(xiàn)
//鏡面強(qiáng)度 float specularStrength = 0.5; //頂點(diǎn)指向觀察點(diǎn)的單位向量 vec3 viewDir = normalize(viewPo - FragPo); //求得光線在頂點(diǎn)的反射線(傳入光源指向頂點(diǎn)的向量) vec3 reflectDir = reflect(-lightDir ,outNormal); // 求得夾角cos值 取256次冪 注意 pow(float,float)函數(shù)參數(shù)類型 float spec = pow(max(dot(viewDir, reflectDir),0.0),256.0); vec3 specular = specularStrength * spec * lightColor; -
綜合光照計算
光照顏色 = (環(huán)境顏色 + 漫反射顏色 + 鏡面反射顏色)*衰減因子 衰減因子 = 1.0/(距離衰減常量 + 線性衰減常量 * 距離 + 二次衰減常量 * 距離的平方) 距離衰減常量、線性衰減常量和二次衰減常量均為常量值環(huán)境光、漫反射光和鏡面光的強(qiáng)度都會受距離的增大而衰減,只有發(fā)射光和全局環(huán)境光的強(qiáng)度不會受影響1)衰減因子計算
//距離衰減常量 float constantPara = 1.0f; //線性衰減常量 float linearPara = 0.09f; //二次衰減因? float quadraticPara = 0.032f; //距離 float LFDistance = length(lightPo - FragPo); //衰減因? float lightWeakPara = 1.0/(constantPara + linearPara * LFDistance + quadraticPara * (LFDistance*LFDistance));2)聚光燈因子計算
聚光燈夾角cos值 = power(max(0,dot(單位光源位置,單位光線向量)),聚光燈指數(shù)); 單位光線向量是從光源指向頂點(diǎn)的單位向量 聚光燈指數(shù),表示聚光燈的亮度程度 公式解讀:單位光源位置 * 單位光線向量點(diǎn)積的聚光燈指數(shù)次方 聚光燈因子 = clamp((外環(huán)的聚光燈角度cos值 - 當(dāng)前頂點(diǎn)的聚光燈角度cos值)/ (外環(huán)的聚光燈?度cos值- 內(nèi)環(huán)聚光燈的?度的cos值),0,1)計算代碼
//內(nèi)錐角cos值 float inCutOff = cos(radians(10.0f)); //外錐角cos值 float outCutOff = cos(radians(15.0f)); //聚光朝向 vec3 spotDir = vec3(-1.2f,-1.0f,-2.0f); //光源指向物體的向量和聚光朝向的 cos值 float theta = dot(lightDir ,normalize(-spotDir)); //內(nèi)外錐角cos差值 float epsilon = inCutOff - outCutOff; //clamp(a,b,c);若b<a<c 則函數(shù)返回值為a 若不是,則返回值最小為b 最大為c // (theta - outCutOff)/epsilon 若theta的角度小于內(nèi)錐角則其值 >=1 若theta的?度大于外錐角則其值<=0 這樣光線就在內(nèi)外錐角之間平滑變化. float intensity = clamp((theta - outCutOff)/epsilon,0.0,1.0); -
綜合光照計算終極公式
光照顏色 = 發(fā)射顏色 + 全局環(huán)境顏色 + (環(huán)境顏色 + 漫反射顏色 + 鏡面反射顏色) * 聚光燈效果 * 衰減因? -
平面光計算GLSL實(shí)現(xiàn)
//環(huán)境因子 float ambientStrength = 0.3; //鏡面強(qiáng)度 float specularStrength = 2.0; //反射強(qiáng)度 float reflectance = 256.0; //平行光方向 vec3 paraLightDir = normalize(vec3(-0.2,-1.0,-0.3)); //環(huán)境光 vec3 ambient = ambientStrength * texture(Texture ,outTexCoord).rgb; //漫反射 vec3 norm = normalize(outNormal); vec3 lightDir = normalize(lightPo - FragPo); //當(dāng)前頂點(diǎn)至光源的單位向量 float diff = max(dot(norm ,paraLightDir),0.0); vec3 diffuse = diff * lightColor*texture(Texture ,outTexCoord).rgb; //鏡面反射 vec3 viewDir = normalize(viewPo - FragPo); vec3 reflectDir = reflect(-paraLightDir ,outNormal); float spec = pow(max(dot(viewDir, reflectDir),0.0),reflectance); vec3 specular = specularStrength * spec * texture(specularTexture ,outTexCoord).rgb; //最終光照顏色 vec3 res = ambient + diffuse + specular; FragColor = vec4(res,1.0); -
點(diǎn)光源計算GLSL實(shí)現(xiàn)
float ambientStrength = 0.3; float specularStrength = 2.0; float reflectance = 256.0; float constantPara = 1.0f; float linearPara = 0.09f; float quadraticPara = 0.032f; //二次項部分因數(shù) //環(huán)境光 vec3 ambient = ambientStrength * texture(Texture ,outTexCoord).rgb; //漫反射 vec3 norm = normalize(outNormal); vec3 lightDir = normalize(lightPo - FragPo); //當(dāng)前頂點(diǎn)至光源的的單位向量 //點(diǎn)光源 float diff = max(dot(norm ,lightDir),0.0); //光源與法線夾角 vec3 diffuse = diff * lightColor*texture(Texture ,outTexCoord).rgb; //鏡面反射 vec3 viewDir = normalize(viewPo - FragPo); vec3 reflectDir = reflect(-lightDir ,outNormal); float spec = pow(max(dot(viewDir, reflectDir),0.0),reflectance); vec3 specular = specularStrength * spec * texture(specularTexture ,outTexCoord).rgb; //光線衰弱 float LFDistance = length(lightPo - FragPo); float lightWeakPara = 1.0/(constantPara + linearPara * LFDistance + quadraticPara * (LFDistance*LFDistance)); vec3 res = (ambient + diffuse + specular)*lightWeakPara; FragColor = vec4(res,1.0);