zoukankan      html  css  js  c++  java
  • OpenGL ES光照计算

    OpenGL ES光照计算是实现立体效果真实性的重要因素,首先需要了解各种光照效果的形成原理,才能更好的利用光照效果做出更加真实的立体场景

    一 光照特性:

    1. 发射光:由物体自身发光

    2. 环境光:就是在环境中充分散射的光,而且无法分辨它的方向

    3. 漫反射光:光线来自某个方向,但在物体上各个方向反射。

    4. 镜面高光:光线来自一个特定的方向,然后在物体表面上以一个特定的方向反射出去

    二 光照计算

    1、环境光计算

    环境光 = 光源的环境光颜色 * 物体的材质颜色

    • 环境光 = 光的颜色 * 材质颜色;
      光是有颜色的,比如红光、绿光等;
      材质颜色也就是纹理颜色。

    2、发射光的计算

    发射颜色 = 物体的反射材质颜色

    • 物体本身是有颜色的,比如手电筒,其本身能发光,发出的光的颜色就是发射颜色。

    3、漫反射光照计算

    • 光照有阴面和阳面,由法线计算光与物体之间的夹角,这个夹角分为入射角和反射角

    漫反射颜色 = 光源的漫反射颜色 * 物体的漫反射材质颜色 * DiffuseFactor

    DiffuseFactor = max(0, dot(N, L));

    4、镜面光计算

    镜面反射颜色 = 光源的镜面光颜色 * 物体的镜面材质颜色 * SpecularFactor

    SpecularFactor = power(max(0, dot(N, H)), shininess);
    H:视线向量E 与光线向量L 的半向量
    dot(N, H):H,N的点积几何意义,平方线与法线夹角的cos值
    shininess:高光的反光度

    5、普通光照计算

    光照颜色 = (环境颜色 + 漫反射颜色 + 镜面反射颜色) * 衰减因子

    衰减因子计算:

     

    6、聚光灯因子

    聚光灯夹角cos值 = power(max(0, dot(单位光源位置, 单位光线向量)), 聚光灯指数);

    单位光线向量:是从光源指向顶点的单位向量
    聚光灯指数:表示聚光灯的亮度程度
    公式解读:单位光源位置 * 单位光线向量 点积 的 聚光灯指数次方

    增加过渡计算
    聚光灯因子 = clamp((外环的聚光灯角度cos值 - 当前顶点的聚光灯角度cos值) / (外环的聚光灯角度cos值 - 内环聚光灯的角度cos值), 0.1)7、光照计算终极公式

    光照颜色 = 发射颜色 + 全局环境颜色 + (环境颜色 + 漫反射颜色 + 镜面颜色) * 聚光灯效果 * 衰减因子

    7.平面光终极公式

    • 平面光也就是平行光,没有具体的方向

    点光源终极公式

    • 比如灯泡光源,点光源是有方向的
    三.GLSL代码实现
    1点光源光照计算
    void pointLight(){
        
        float ambientStrength = 0.3;    //环境因子
        float specularStrength = 2.0;   //镜面强度
        float reflectance = 256.0;      //反射率
    
        float constantPara = 1.0;     //距离衰减常量
        float linearPara = 0.09;      //线性衰减常量
        float quadraticPara = 0.032;  //二次衰减常量
    
        //环境光 = 环境因子 * 物体的材质颜色
        vec3 ambient = ambientStrength * texture(Texture,outTexCoord).rgb;
    
        //漫反射
        vec3 norm = normalize(outNormal);
        //当前顶点 至 光源的的单位向量
        vec3 lightDir = normalize(lightPo - FragPo);
        //DiffuseFactor=光源与法线夹角 max(0,dot(N,L))
        float diff = max(dot(norm,lightDir),0.0);
        //漫反射光颜色计算 = 光源的漫反射颜色 * 物体的漫发射材质颜色 * DiffuseFactor
        vec3 diffuse = diff * lightColor*texture(Texture,outTexCoord).rgb;
    
        //镜面反射
        vec3 viewDir = normalize(viewPo - FragPo);
        // reflect (genType I, genType N),返回反射向量
        vec3 reflectDir = reflect(-lightDir,outNormal);
        //SpecularFactor = power(max(0,dot(N,H)),shininess)
        float spec = pow(max(dot(viewDir, reflectDir),0.0),reflectance);
        //镜面反射颜色 = 光源的镜面光的颜色 * 物体的镜面材质颜色 * SpecularFactor
        vec3 specular = specularStrength * spec * texture(specularTexture,outTexCoord).rgb;
    
        //衰减因子计算
        float LFDistance = length(lightPo - FragPo);
        //衰减因子 =  1.0/(距离衰减常量 + 线性衰减常量 * 距离 + 二次衰减常量 * 距离的平方)
        float lightWeakPara = 1.0/(constantPara + linearPara * LFDistance + quadraticPara * (LFDistance*LFDistance));
        
        //光照颜色 =(环境颜色 + 漫反射颜色 + 镜面反射颜色)* 衰减因子
        vec3 res = (ambient + diffuse + specular)*lightWeakPara;
    
        //最终输出的颜色
        FragColor = vec4(res,1.0);
    
    }

    二。平行光光照计算

    void parallelLight(){
      
        float ambientStrength = 0.3;    //环境因子
        float specularStrength = 2.0;   //镜面强度
        float reflectance = 256.0;      //反射率
    
        //平行光方向
        vec3 paraLightDir = normalize(vec3(-0.2,-1.0,-0.3));
    
        //环境光 = 环境因子 * 物体的材质颜色
        vec3 ambient = ambientStrength * texture(Texture,outTexCoord).rgb;
    
        //漫反射
        vec3 norm = normalize(outNormal);
        //当前顶点至光源的的单位向量
        vec3 lightDir = normalize(lightPo - FragPo);
        //DiffuseFactor=光源与paraLightDir 平行光夹角 max(0,dot(N,L))
        float diff = max(dot(norm,paraLightDir),0.0);
        //漫反射光颜色计算 = 光源的漫反射颜色 * 物体的漫发射材质颜色 * DiffuseFactor
        vec3 diffuse = diff * lightColor * texture(Texture,outTexCoord).rgb;
    
        //镜面反射
        vec3 viewDir = normalize(viewPo - FragPo);
        // reflect (genType I, genType N),返回反射向量 -paraLightDir平行光
        vec3 reflectDir = reflect(-paraLightDir,outNormal);
        //SpecularFactor = power(max(0,dot(N,H)),shininess)
        float spec = pow(max(dot(viewDir, reflectDir),0.0),reflectance);
        //镜面反射颜色 = 光源的镜面光的颜色 * 物体的镜面材质颜色 * SpecularFactor
        vec3 specular = specularStrength * spec * texture(specularTexture,outTexCoord).rgb;
    
        //距离衰减常量
        float constantPara = 1.0;
        //线性衰减常量
        float linearPara = 0.09;
        //二次衰减常量
        float quadraticPara = 0.032;
        //衰减因子计算
        float LFDistance = length(lightPo - FragPo);
        //衰减因子 =  1.0/(距离衰减常量 + 线性衰减常量 * 距离 + 二次衰减常量 * 距离的平方)
        float lightWeakPara = 1.0/(constantPara + linearPara * LFDistance + quadraticPara * (LFDistance*LFDistance));
    
        //光照颜色 =(环境颜色 + 漫反射颜色 + 镜面反射颜色)* 衰减因子
        vec3 res = (ambient + diffuse + specular)*lightWeakPara;
        
        //最终输出的颜色
        FragColor = vec4(res,1.0);
    }

    3.聚光灯光照计算

    void Spotlight(){
       
        float ambientStrength = 0.3;    //环境因子
        float specularStrength = 2.0;   //镜面强度
        float reflectance = 256.0;      //反射率
    
        //环境光 = 环境因子 * 物体的材质颜色
        vec3 ambient = ambientStrength * texture(Texture,outTexCoord).rgb;
    
        //漫反射
        vec3 norm = normalize(outNormal);
        vec3 lightDir = normalize(lightPo - FragPo);    //当前顶点 至 光源的的单位向量
        //DiffuseFactor=光源与paraLightDir lightDir夹角 max(0,dot(N,L))
        float diff = max(dot(norm,lightDir),0.0);   //光源与法线夹角
        //漫反射光颜色计算 = 光源的漫反射颜色 * 物体的漫发射材质颜色 * DiffuseFactor
        vec3 diffuse = diff * lightColor*texture(Texture,outTexCoord).rgb;
    
        //镜面反射
        vec3 viewDir = normalize(viewPo - FragPo);
         // reflect (genType I, genType N),返回反射向量
        vec3 reflectDir = reflect(-lightDir,outNormal);
        //SpecularFactor = power(max(0,dot(N,H)),shininess)
        float spec = pow(max(dot(viewDir, reflectDir),0.0),reflectance);
        //镜面反射颜色 = 光源的镜面光的颜色 * 物体的镜面材质颜色 * SpecularFactor
        vec3 specular = specularStrength * spec * texture(specularTexture,outTexCoord).rgb;
    
        float constantPara = 1.0;    //距离衰减常量
        float linearPara = 0.09;     //线性衰减常量
        float quadraticPara = 0.032; //二次衰减常量
        
        //衰减因子计算
        float LFDistance = length(lightPo - FragPo);
        //衰减因子 =  1.0/(距离衰减常量 + 线性衰减常量 * 距离 + 二次衰减常量 * 距离的平方)
        float lightWeakPara = 1.0/(constantPara + linearPara * LFDistance + quadraticPara * (LFDistance*LFDistance));
    
        //聚光灯切角 (一些复杂的计算操作 应该让CPU做,提高效率,不变的量也建议外部传输,避免重复计算)
        float inCutOff = cos(radians(10.0));
        float outCutOff = cos(radians(15.0));
        vec3 spotDir = vec3(-1.2,-1.0,-2.0);
        
        //聚光灯因子 = clamp((外环的聚光灯角度cos值 - 当前顶点的聚光灯角度cos值)/(外环的聚光灯角度cos值- 内环聚光灯的角度的cos值),0,1);
        float theta = dot(lightDir,normalize(-spotDir));
        //(外环的聚光灯角度cos值- 内环聚光灯的角度的cos值)
        float epsilon  = inCutOff - outCutOff;
        //(外环的聚光灯角度cos值 - 当前顶点的聚光灯角度cos值) / (外环的聚光灯角度cos值- 内环聚光灯的角度的cos值)
        float intensity = clamp((theta - outCutOff)/epsilon,0.0,1.0);
        vec3 res = (ambient + diffuse + specular)*intensity*lightWeakPara;
    
        FragColor = vec4(res,1.0);
    }

    四.GLKit光照使用

    iOS中GLKit封装好了光照计算效果,只需调用相应的接口就能实现一些简单的光照效果

    按照OpenGL ES 1.1规范,GLKEffectPropertyLight为GLKEffect提平行光或点光源光照效果,根据OpenGL ES 1.1规范,光的位置和方向被转换通过模型视图矩阵。因此,GLKEffectPropertyLight有一个转换属性,如果需要光转换,则必须显式设置转换属性光属性。为了使照明计算正常工作,GLKEffectPropertyLight的客户端必须启用顶点属性数组GLKVertexAttribNormal来为

    它提供法线

    GLKit中GLKBaseEffect提供了3个光源可供设置类型为GLKEffectProperty

    effect.light0,effect.light1,effect.light2每个光源可以设置他的类型位置等参数

     

    代码地址:https://github.com/duzhaoquan/OpenGLESLoadImage

  • 相关阅读:
    常用的几个JavaScript调试技巧
    一个能够编写、运行SQL查询并可视化结果的Web应用:SqlPad
    一个能够编写、运行SQL查询并可视化结果的Web应用:SqlPad
    一个能够编写、运行SQL查询并可视化结果的Web应用:SqlPad
    67 个JavaScript和CSS实用工具、库与资源
    67 个JavaScript和CSS实用工具、库与资源
    67 个JavaScript和CSS实用工具、库与资源
    SQL日常维护的语句
    ACM2096_小明A+B
    Janet Wu price
  • 原文地址:https://www.cnblogs.com/duzhaoquan/p/12957144.html
Copyright © 2011-2022 走看看