OpenGL ES光照計算

光照是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);
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 光照基礎(chǔ) 1.環(huán)境光照(ambient) 2.漫反射光照(diffuse) 3.鏡面光照(specular) 光照...
    ChiLeung閱讀 626評論 0 0
  • 環(huán)境光的計算 環(huán)境光 = 光源的環(huán)境光顏色 * 物體的材質(zhì)顏? 發(fā)射光的計算 發(fā)射顏色 = 物體的反射材質(zhì)顏? 漫...
    Tobesky閱讀 1,861評論 0 0
  • 光照是個很復(fù)雜的話題,尤其是多光源,陰影的計算。在這篇文章中,我會詳細(xì)介紹不同類型光的性質(zhì)以及物體的材質(zhì)屬性,以及...
    Daniel_Harvey閱讀 1,129評論 0 0
  • 頂點(diǎn)著色器代碼 片元著色器代碼 點(diǎn)光源版本 平行光版本 聚光版本 GLKit層部分核心代碼 設(shè)置VBO 渲染
    Tobesky閱讀 545評論 0 0
  • 對于兒童是否應(yīng)該吃肉喝牛奶的問題,身邊總是有不同的聲音。 支持派認(rèn)為肉奶能夠提供素食中所沒有的營養(yǎng)成分,兒童處于生...
    達(dá)文喜閱讀 624評論 2 2

友情鏈接更多精彩內(nèi)容