OpenGL ES 关于光照计算

简介: 有关光照的代码公式, 在此用CC老师已经写好的代码做一个记录, 方便以后使用的时候查询.

有关光照的代码公式, 在此用CC老师已经写好的代码做一个记录, 方便以后使用的时候查询.


记录一个函数-->根据你的设置返回一个4x4矩阵变换的世界坐标系坐标。


//获取世界坐标系去模型矩阵中.  
    /*  
     LKMatrix4 GLKMatrix4MakeLookAt(float eyeX, float eyeY, float eyeZ,  
     float centerX, float centerY, float centerZ,  
     float upX, float upY, float upZ)  
     等价于 OpenGL 中  
     void gluLookAt(GLdouble eyex,GLdouble eyey,GLdouble eyez,GLdouble centerx,GLdouble centery,GLdouble centerz,GLdouble upx,GLdouble upy,GLdouble upz);  
     目的:根据你的设置返回一个4x4矩阵变换的世界坐标系坐标。  
     参数1:眼睛位置的x坐标  
     参数2:眼睛位置的y坐标  
     参数3:眼睛位置的z坐标  
     第一组:就是脑袋的位置  
     参数4:正在观察的点的X坐标  
     参数5:正在观察的点的Y坐标  
     参数6:正在观察的点的Z坐标  
     第二组:就是眼睛所看物体的位置  
     参数7:摄像机上向量的x坐标  
     参数8:摄像机上向量的y坐标  
     参数9:摄像机上向量的z坐标  
     第三组:就是头顶朝向的方向(因为你可以头歪着的状态看物体)  
     */  
    GLKMatrix4 view1 = GLKMatrix4MakeLookAt(camX,camX,camZ,0,0,0,0,1,0);


其中注意 in out 相对应的输入输入属性写法, 其实与attribute varying的意思是一样的, 注意此处的写法

以及在外部的使用与attribute varying的区别


glEnableVertexAttribArray(0);  
    glEnableVertexAttribArray(1);  
    glEnableVertexAttribArray(2);  
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void*)NULL);  
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void*)(3*sizeof(float)));  
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8*sizeof(float), (void*)(6*sizeof(float)));


  • 顶点着色器相应代码 (在此的作用 主要用来相应解释片元着色器代码)


#version 300 es  
layout(location = 0) in vec3 position;  //顶点  
layout(location = 1) in vec3 normal;    //法向量  
layout(location = 2) in vec2 texCoord;  //纹理坐标  
uniform mat4 view;  
uniform mat4 projection;  
out vec3 outNormal; //法向量  
out vec3 FragPo;    //顶点在世界坐标位置  
out vec2 outTexCoord;//纹理坐标  
void main()  
{  
    FragPo = position;  
    outNormal = normal;  
    outTexCoord = texCoord;  
    gl_Position = projection * view * vec4(position,1.0);  
}


  • 重点查看片元着色器中 光线的计算公式


#version 300 es  
precision mediump float;  
out vec4 FragColor;  
uniform vec3 lightColor;    //光源颜色  
uniform vec3 lightPo;       //光源位置  
uniform vec3 viewPo;        //视角位置  
uniform sampler2D Texture;          //物体纹理  
uniform sampler2D specularTexture;  //镜面纹理  
in vec2 outTexCoord;    //纹理坐标  
in vec3 outNormal;      //顶点法向量  
in vec3 FragPo;         //顶点坐标  
//点光源版本
void pointLight(){
    float ambientStrength = 0.3;    //环境因子  
    float specularStrength = 2.0;   //镜面强度  
    float reflectance = 256.0;      //反射率  
    float constantPara = 1.0f;     //距离衰减常量  
    float linearPara = 0.09f;      //线性衰减常量  
    float quadraticPara = 0.032f;  //二次衰减常量  
    //环境光 = 环境因子 * 物体的材质颜色  
    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 paraLightDir =normalize(vec3(-1,-1,1));  
    //环境光 = 环境因子 * 物体的材质颜色  
    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.0f;  
    //线性衰减常量  
    float linearPara = 0.09f;  
    //二次衰减常量  
    float quadraticPara = 0.032f;  
    //衰减因子计算  
    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 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.0f;    //距离衰减常量  
    float linearPara = 0.09f;     //线性衰减常量  
    float quadraticPara = 0.032f; //二次衰减常量  
    //衰减因子计算  
    float LFDistance = length(lightPo - FragPo);  
    //衰减因子 =  1.0/(距离衰减常量 + 线性衰减常量 * 距离 + 二次衰减常量 * 距离的平方)  
    float lightWeakPara = 1.0/(constantPara + linearPara * LFDistance + quadraticPara * (LFDistance*LFDistance));  
    //聚光灯切角 (一些复杂的计算操作 应该让CPU做,提高效率,不变的量也建议外部传输,避免重复计算)  
    float inCutOff = cos(radians(10.0f));  
    float outCutOff = cos(radians(15.0f));  
    vec3 spotDir = vec3(-1.2f,-1.0f,-2.0f);  
    //聚光灯因子 = 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);  
}  
void DiffultLight(){  
    float ambientStrength = 0.3;    //环境因子  
    //环境光 = 环境因子 * 物体的材质颜色  
    vec3 ambient = ambientStrength * texture(Texture,outTexCoord).rgb;  
    //光源方向  
    //vec3 paraLightDir =normalize(vec3(0,1,0));  
    //漫反射  
    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 res = ambient + diffuse;  
     FragColor = vec4(res,1.0);  
}
void main()  
{
    //聚光版本  
    //Spotlight();  
    //点光源版本  
    //pointLight();  
    //平行光版本  
    //parallelLight();  
     DiffultLight();  
}




目录
相关文章
|
8月前
|
XML 小程序 Java
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)
149 0
|
算法
QT+OpenGL高级光照 Blinn-Phong和Gamma校正
冯氏光照:视线与反射方向之间的夹角不小于90度,镜面光分量会变成0.0(不是很合理,会有清晰的分界线) Blinn-Phone模型采用了半程向量,即光线与视线夹角一般方向上的一个单位向量。当半程向量与法线向量越接近,镜面光分量就越大。
138 0
QT+OpenGL光照2
在现实世界中,每个物体会对光照产生不同的反应
51 0
QT+OpenGL光照
现实生活中看到的物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的颜色 太阳光能被看见的白光是多找演的的组合
63 0
|
存储 编解码 算法
Opengl ES之LUT滤镜(上)
Opengl ES之连载系列
492 0
|
数据安全/隐私保护 开发者
OpenGL ES 多目标渲染(MRT)
Opengl ES连载系列
339 0
|
数据安全/隐私保护 索引
Opengl ES之纹理数组
Opengl ES连载系列
270 0
|
数据安全/隐私保护
Opengl ES之水印贴图
Opengl ES之连载系列
166 0
|
缓存 C++
Opengl ES之FBO
Opengl ES连载系列
161 0
|
Java 数据安全/隐私保护 Android开发
Opengl ES之矩阵变换(下)
Opengl ES连载系列
143 0