光照基礎(chǔ)
- 環(huán)境光
- 漫反射光
- 鏡面光
光照特性
材質(zhì)屬性
- ?泛射材質(zhì)
- ?漫反射材質(zhì)?
- ?鏡面反射材質(zhì)
- ?發(fā)射材質(zhì)
光照計(jì)算
環(huán)境光的計(jì)算
1. 環(huán)境光的計(jì)算
? ? ?????環(huán)境光 = 光源的環(huán)境光顏色 * 物體的材質(zhì)顏色
2. 環(huán)境光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;
?l_FragColor = vec4(result, 1.0);
}
發(fā)射光的計(jì)算
? ? ? ? 發(fā)射顏色 = 物體反射材質(zhì)的顏色
漫反射光的計(jì)算
? ??????漫反射顏?色?=?光源的漫反射顏?色?*?物體的漫發(fā)射材質(zhì)顏?色?* DiffuseFactor
? ??????DiffuseFactor = max(0,dot(N,L))
????????漫反射因子DiffuseFactor?是光線與頂點(diǎn)法線向量的點(diǎn)積
? ? ? ? 漫反射光計(jì)算代碼實(shí)現(xiàn)
? ? ? ? ? ? uniform vec3 lightColor;
? ? ? ? ? ? ?uniform vec3 lightPo;
? ? ? ? ? ? uniform vec3 objectColor;
? ? ? ? ? ? uniform vec3 viewPo;
? ? ? ? ? ? varying vec3 outNormal;
? ? ? ? ? ? //確保法線為單位向量
? ? ? ? ? ?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);
鏡面光計(jì)算
N : 平?面法線
?I : 入射光線?
H : 反射光線?
E : 視線
? : 視點(diǎn)與反射光的夾角
鏡面反射顏色?=?光源的鏡面光的顏色?*?物體的鏡面材質(zhì)顏色?* SpecularFactor
SpecularFactor = power(max(0,dot(N,H)),shininess)
H?:視線向量E?與 光線向量L?的半向量
dot(N,H):H,N的點(diǎn)積幾何意義,平方線與法線夾角的cos值
shiniess :??高光的反光度;
鏡面光計(jì)算代碼實(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;
光照計(jì)算
? ??????光照顏色?=(環(huán)境顏色?+?漫反射顏色?+?鏡面反射顏色)*?衰減因?
? ? ??
衰減因子
衰減因? = 1.0/(距離衰減常量?+?線性衰減常量?*?距離?+ 二次衰減常量?*?距離的平?)
注意:環(huán)境光巫财,漫反射光和鏡面光的強(qiáng)度都會(huì)受距離的增大而衰減,只有發(fā)射光和全局環(huán)境光的強(qiáng)度不會(huì)受影響
衰減因子代碼
//距離衰減常量
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));
聚光因子
聚光燈夾角cos值?= power(max(0,dot(單位光源位置阀蒂,單位光線向量)),聚光燈指數(shù));
- 單位光線向量:從光源指向頂點(diǎn)的單位向量?
- 聚光燈指數(shù):表示聚光燈的亮度程度
- 公式解讀:單位光源位置 *?單位光線向量點(diǎn)積的聚光燈指數(shù)次?啄育。
聚光燈過度計(jì)算代碼實(shí)現(xiàn)
//(?一些復(fù)雜的計(jì)算操作 應(yīng)該讓CPU做,提?高效率,不不變的量量也建議外部傳輸,避免 重復(fù)計(jì)算)
//內(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);
光照計(jì)算終極公式
光照顏色?=?發(fā)射顏色?+?全局環(huán)境顏色?+ (環(huán)境顏色?+?漫反射顏色?+?鏡?反射顏色) *?聚光燈效果?*?衰減因?
平面光計(jì)算代碼實(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)光源計(jì)算代碼實(shí)現(xiàn)
float ambientStrength = 0.3;//環(huán)境因子
float specularStrength = 2.0;//鏡面強(qiáng)度
float reflectance = 256.0;//反射強(qiáng)度
float constantPara = 1.0f;//常量
float linearPara = 0.09f;//線性部分因子
float quadraticPara = 0.032f; //二次項(xiàng)部分因數(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);