GLSL 中的光照计算
理论知识转载地址:http://blog.csdn.net/ym19860303/article/details/25545933
1.Lambert模型(漫反射)
环境光:
Iambdiff = Kd*Ia
其中Ia 表示环境光强度,Kd(0<K<1)为材质对环境光的反射系数,Iambdiff是漫反射体与环境光交互反射的光强。
方向光:
Ildiff = Kd * Il * Cos(θ)
其中Il是点光源强度,θ是入射光方向与顶点法线的夹角,称入射角(0<=A<=90°),Ildiff是漫反射体与方向光交互反射的光强,若 N为顶点单位法向量,L表示从顶点指向光源的单位向量(注意顶点指向光源),则Cos(θ)等价于dot(N,L),故又有:
Ildiff = Kd * Il * dot(N,L)
最后综合环境光和方向光源,Lambert光照模型可以写成:
Idiff = Iambdiff + Ildiff = Kd * Ia + Kd * Il * dot(N,L)
2.Phong模型(镜面反射)
Phong模型认为镜面反射的光强与反射光线和视线的夹角相关:
Ispec = Ks * Il * ( dot(V,R) )^Ns
其中Ks 为镜面反射系数,Ns是高光指数,V表示从顶点到视点的观察方向,R代表反射光方向。由于反射光的方向R可以通过入射光方向L(从顶点指向光源)和物体的法向量求出,
R + L = 2 * dot(N, L) * N 即 R = 2 * dot(N,L) * N - L
所以最终的计算式为:
Ispec = Ks * Il * ( dot(V, (2 * dot(N,L) * N – L ) )^Ns
3.Blinn-Phong光照模型(修正镜面光)
Blinn-Phong是一个基于Phong模型修正的模型,其公式为:
Ispec = Ks * Il * ( dot(N,H) )^Ns
其中N是入射点的单位法向量,H是光入射方向L和视点方向V的中间向量,通常也称之为半角向量(半角向量被广泛用于各类光照模型,原因不但在于半角向量蕴含的信息价值,也在于半角向量是很简单的计算:H = (L + V) / |L + V| )。
4.Rendering Equation(全局光照模型)
Rendering Equation 是Kajia在1986年提出的,
Lo(X, Wo) = Le(X, Wo) + ∫fr(X, Wi, Wo) Li(X, Wi) dot(N, Wi) dWi
其中X表示入射点,Lo(X, Wo)即从物体表面X点,沿方向Wo反射的光强,Le(X, Wo)表示从物体表面X以方向Wo 发射出去的光强,该值仅对自发光体有效,fr(X, Wi, Wo)为,入射光线方向为Wi, 照射到点X上,然后从Wo方向发射出去的BRDF值,Li(X, Wi)为入射方向为Wi照射到点X上的入射光强,N表示点X处的法向量,然后对入射方向进行积分(因为光线入射的方向是四面八方的,积分的意义是对每个方向进行一遍计算后相加),计算的结果就是全局光照的辐射率。
对于单个点光源照射到不会自发光的物体上,公式可以简化成:
Lo(X, Wo) = fr(X, Wi, Wo) Li(X, Wi) dot(N, Wi)
这个公式非常有用,通常会将该公式分解为漫反射表达式和镜面表达式之和。对于漫反射表面,BRDF可以忽略不计,因为它总是返回某个恒定值,所以可以写成如下形式:
Lo(X, Wo) = Idiff + frs(X, Wi, Wo) Li(X, Wi) dot(N, Wi)
其中Idiff表示漫反射分量,使用公式的计算方法,frs(X, Wi, Wo)表示镜面反射的BRDF函数,前面的Phong高光模型,其实是rendering equation在单一光源下针对理想镜面反射的特定推导,对于Phong高光而言:
frs(X, Wi, Wo) = Ks (dot(N, H)^Ns / dot(N, Wi)
基于GLSL的实现(所有光照和材质参数在实际应用时,应该从常量改为uniform,由外部进行控制):
// 在顶点着色器中处理光照计算(环境光+漫射光+镜面反射)
const char* ccPositionTextureColorForLight1_v = " \
uniform vec2 translate; \n\
\n\
attribute vec4 a_position; \n\
attribute vec4 a_color; \n\
attribute vec2 a_texCoord; \n\
attribute vec3 a_normal; \n\
\n\
#ifdef GL_ES \n\
varying mediump vec4 v_color; \n\
varying mediump vec2 v_texCoord; \n\
#else \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
#endif \n\
\n\
const vec3 lightAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightSpecular = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialSpecular = vec3(1.0, 1.0, 1.0); \n\
const int shininess = 8; // 0-128 \n\
\n\
const vec3 eyePosition = vec3(512.0, 128.0, 442.0); \n\
const vec3 lightDirection = vec3(1.0, 1.0, 1.0); \n\
\n\
void main() { \n\
vec4 position = CC_MVMatrix * a_position; \n\
position.x += translate.x; \n\
position.y += translate.y; \n\
gl_Position = CC_PMatrix * position; \n\
\n\
vec3 normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz; \n\
vec3 n_normal = normalize(normal); \n\
vec3 n_lightDirection = normalize(lightDirection); \n\
float cosNL = max(dot(n_normal, n_lightDirection), 0.0); \n\
vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL; \n\
\n\
vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0); \n\
\n\
vec3 n_eyePosition = normalize(eyePosition - position.xyz); \n\
vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection; \n\
vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyePosition, reflection), 0.0), shininess), 1.0); \n\
\n\
v_color = a_color * (diffuse + ambient + specular); \n\
v_texCoord = a_texCoord; \n\
} \n\
";
const char* ccPositionTextureColorForLight1_f = " \
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
\n\
void main() { \n\
vec4 color = v_color * texture2D(CC_Texture0, v_texCoord); \n\
color.a = 1.0; \n\
\n\
gl_FragColor = color; \n\
} \n\
";
效果:
// 在片段着色器中处理光照计算(环境光+漫反射+镜面反射)
const char* ccPositionTextureColorForLight2_v = " \
uniform vec2 translate; \n\
\n\
attribute vec4 a_position; \n\
attribute vec4 a_color; \n\
attribute vec2 a_texCoord; \n\
attribute vec3 a_normal; \n\
\n\
#ifdef GL_ES \n\
varying mediump vec4 v_position; \n\
varying mediump vec4 v_color; \n\
varying mediump vec2 v_texCoord; \n\
varying mediump vec3 v_normal; \n\
#else \n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
#endif \n\
\n\
void main() { \n\
vec4 position = CC_MVMatrix * a_position; \n\
position.x += translate.x; \n\
position.y += translate.y; \n\
gl_Position = CC_PMatrix * position; \n\
\n\
v_position = position; \n\
v_color = a_color; \n\
v_texCoord = a_texCoord; \n\
v_normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz; \n\
} \n\
";
const char* ccPositionTextureColorForLight2_f = " \
const vec3 lightAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightSpecular = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialSpecular = vec3(1.0, 1.0, 1.0); \n\
const int shininess = 8; // 0-128 \n\
\n\
const vec3 eyePosition = vec3(512.0, 128.0, 442.0); \n\
const vec3 lightDirection = vec3(1.0, 1.0, 1.0); \n\
\n\
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
\n\
void main() { \n\
vec4 color = v_color * texture2D(CC_Texture0, v_texCoord); \n\
color.a = 1.0; \n\
\n\
vec3 normal = v_normal; \n\
vec3 n_normal = normalize(normal); \n\
vec3 n_lightDirection = normalize(lightDirection); \n\
float cosNL = max(dot(n_normal, n_lightDirection), 0.0); \n\
vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL; \n\
\n\
vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0); \n\
\n\
vec3 n_eyeDirection = normalize(eyePosition - v_position.xyz); \n\
vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection; \n\
vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyeDirection, reflection), 0.0), shininess), 1.0); \n\
//vec3 reflection = normalize(n_eyeDirection + n_lightDirection); \n\
//vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_normal, reflection), 0.0), shininess), 1.0); \n\
\n\
gl_FragColor = color * (ambient + diffuse + specular); \n\
} \n\
";
效果:
// 在片段着色器中处理光照计算(环境光+漫反射+镜面反射+衰减系数)
const char* ccPositionTextureColorForLight3_v = " \
uniform vec2 translate; \n\
\n\
attribute vec4 a_position; \n\
attribute vec4 a_color; \n\
attribute vec2 a_texCoord; \n\
attribute vec3 a_normal; \n\
\n\
#ifdef GL_ES \n\
varying mediump vec4 v_position; \n\
varying mediump vec4 v_color; \n\
varying mediump vec2 v_texCoord; \n\
varying mediump vec3 v_normal; \n\
varying float v_distance; \n\
#else \n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
varying float v_distance; \n\
#endif \n\
\n\
void main() { \n\
vec4 position = CC_MVMatrix * a_position; \n\
position.x += translate.x; \n\
position.y += translate.y; \n\
gl_Position = CC_PMatrix * position; \n\
\n\
v_position = position; \n\
v_color = a_color; \n\
v_texCoord = a_texCoord; \n\
v_normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz; \n\
} \n\
";
const char* ccPositionTextureColorForLight3_f = " \
const vec3 lightAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightSpecular = vec3(1.0, 1.0, 1.0); \n\
const float lightAttenuationConst = 1.0; \n\
const float lightAttenuationLinear = 0.0002; \n\
const float lightAttenuationQuadratic = 0.000001; \n\
const vec3 materialAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialSpecular = vec3(1.0, 1.0, 1.0); \n\
const int shininess = 8; // 0-128 \n\
\n\
const vec3 lightPosition = vec3(1024.0, 512.0, 100.0); \n\
const vec3 eyePosition = vec3(512.0, 256.0, 442.0); \n\
\n\
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
varying float v_distance; \n\
\n\
void main() { \n\
vec4 color = v_color * texture2D(CC_Texture0, v_texCoord); \n\
color.a = 1.0; \n\
\n\
vec3 lightDirection = lightPosition - v_position.xyz; \n\
float distance = length(lightDirection); \n\
float atten = 1.0 / (lightAttenuationConst + lightAttenuationLinear * distance + lightAttenuationQuadratic * distance * distance); \n\
\n\
vec3 normal = v_normal; \n\
vec3 n_normal = normalize(normal); \n\
vec3 n_lightDirection = normalize(lightDirection); \n\
float cosNL = max(dot(n_normal, n_lightDirection), 0.0); \n\
vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL; \n\
\n\
vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0); \n\
\n\
vec3 n_eyeDirection = normalize(eyePosition - v_position.xyz); \n\
vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection; \n\
vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyeDirection, reflection), 0.0), shininess), 1.0); \n\
//vec3 reflection = normalize(n_eyeDirection + n_lightDirection); \n\
//vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_normal, reflection), 0.0), shininess), 1.0); \n\
\n\
float colorA = color.a; \n\
gl_FragColor = vec4(color.rgb * (ambient + diffuse + specular).xyz * atten, colorA); \n\
} \n\
";
效果:
// 在片段着色器中处理光照计算(环境光+漫反射+镜面反射+聚光灯+衰减系数)
const char* ccPositionTextureColorForLight4_v = " \
uniform vec2 translate; \n\
const vec3 spotlightPosition = vec3(512.0, 256.0, 120.0); \n\
const vec3 lightPosition = vec3(512.0, 256.0, 442.0); \n\
const vec3 eyePosition = vec3(512.0, 256.0, 442.0); \n\
\n\
attribute vec4 a_position; \n\
attribute vec4 a_color; \n\
attribute vec2 a_texCoord; \n\
attribute vec3 a_normal; \n\
\n\
#ifdef GL_ES \n\
varying mediump vec4 v_position; \n\
varying mediump vec4 v_color; \n\
varying mediump vec2 v_texCoord; \n\
varying mediump vec3 v_normal; \n\
varying mediump float v_distance; \n\
varying mediump vec3 v_lightDirection; \n\
varying mediump vec3 v_spotlightDirection; \n\
#else \n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
varying float v_distance; \n\
varying vec3 v_lightDirection; \n\
varying vec3 v_spotlightDirection; \n\
#endif \n\
\n\
void main() { \n\
vec4 position = CC_MVMatrix * a_position; \n\
position.x += translate.x; \n\
position.y += translate.y; \n\
gl_Position = CC_PMatrix * position; \n\
\n\
v_position = position; \n\
v_color = a_color; \n\
v_texCoord = a_texCoord; \n\
v_normal = (CC_MVMatrix * vec4(a_normal, 1.0)).xyz; \n\
\n\
vec3 lightDirection = lightPosition - position.xyz; \n\
vec3 spotlightDirection = spotlightPosition - position.xyz; \n\
v_distance = length(lightDirection); \n\
v_lightDirection = normalize(lightDirection); \n\
v_spotlightDirection = normalize(spotlightDirection); \n\
} \n\
";
const char* ccPositionTextureColorForLight4_f = " \
const vec3 lightAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 lightSpecular = vec3(1.0, 1.0, 1.0); \n\
const float lightAttenuationConst = 1.0; \n\
const float lightAttenuationLinear = 0.001; \n\
const float lightAttenuationQuadratic = 0.000001; \n\
const vec3 materialAmbient = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialDiffuse = vec3(1.0, 1.0, 1.0); \n\
const vec3 materialSpecular = vec3(1.0, 1.0, 1.0); \n\
const int shininess = 8; // 0-128 \n\
const int lightSpotExponent = 1; \n\
const float lightSpotCosCutoff = cos(45.0 / 180.0 * 3.1415926); \n\
\n\
const vec3 lightPosition = vec3(512.0, 256.0, 442.0); \n\
const vec3 eyePosition = vec3(512.0, 256.0, 442.0); \n\
\n\
#ifdef GL_ES \n\
precision lowp float; \n\
#endif \n\
\n\
varying vec4 v_position; \n\
varying vec4 v_color; \n\
varying vec2 v_texCoord; \n\
varying vec3 v_normal; \n\
varying float v_distance; \n\
varying vec3 v_lightDirection; \n\
varying vec3 v_spotlightDirection; \n\
\n\
void main() { \n\
vec4 color = v_color * texture2D(CC_Texture0, v_texCoord); \n\
color.a = 1.0; \n\
\n\
// vec3 lightDirection = lightPosition - v_position.xyz; \n\
vec3 n_spotDirection = normalize(lightPosition - vec3(512.0, 256.0, 0.0)); \n\
vec3 n_spotlightDirection = normalize(v_spotlightDirection); \n\
// float distance = length(lightDirection); \n\
float atten = 1.0 / (lightAttenuationConst + lightAttenuationLinear * v_distance + lightAttenuationQuadratic * v_distance * v_distance); \n\
\n\
vec3 normal = v_normal; \n\
vec3 n_normal = normalize(normal); \n\
vec3 n_lightDirection = normalize(v_lightDirection); \n\
float cosNL = max(dot(n_normal, n_lightDirection), 0.0); \n\
vec4 diffuse = vec4(lightDiffuse * materialDiffuse, 1.0) * cosNL; \n\
\n\
vec4 ambient = vec4(lightAmbient * materialAmbient, 1.0); \n\
\n\
vec3 n_eyeDirection = normalize(eyePosition - v_position.xyz); \n\
vec3 reflection = 2 * max(dot(n_normal, n_lightDirection), 0.0) * n_normal - n_lightDirection; \n\
vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_eyeDirection, reflection), 0.0), shininess), 1.0); \n\
//vec3 reflection = normalize(n_eyeDirection + n_lightDirection); \n\
//vec4 specular = vec4(lightSpecular * materialSpecular * pow(max(dot(n_normal, reflection), 0.0), shininess), 1.0); \n\
\n\
float cosSpot = dot(-1 * n_spotDirection, -1 * n_spotlightDirection); \n\
if (cosSpot > lightSpotCosCutoff) \n\
{ \n\
float spotEffect = pow(cosSpot, lightSpotExponent); \n\
atten += spotEffect; \n\
} \n\
float colorA = color.a; \n\
gl_FragColor = vec4(color.rgb * (ambient + diffuse + specular).xyz * atten, colorA); \n\
} \n\
";
效果:
GLSL 中的光照计算的更多相关文章
- GLSL逐像素光照 【转】
转载:http://blog.csdn.net/hgl868/article/details/7872414 逐像素的方向光(Directional Light per Pixel) 这一节将把前面的 ...
- GLSL逐顶点光照[转]
转载:http://blog.csdn.net/hgl868/article/details/7872350 引言 在OpenGL中有三种类型的光:方向光(directional).点光(point) ...
- 【Unity Shaders】Shader中的光照
写在前面 自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已.当然,我相信这是因为我们写得少...不过这也是由于官方文档对这方面介绍很少的缘故, ...
- 关于Unity中的光照(七)
全局光照 GI 这里所说的反射就是,一个红色的物体,当太阳照射它的时候,它周围的物体也会变得有点红. 1:Realtime每帧都会计算光照,实时光照是不会反射的,所以它的光影显得单调;2:Baked ...
- 关于Unity中的光照(五)
Mobile Diffuse Unity自带的一种shader,用的比较多,性能还可以.我们默认创建的unit shader基本和它一致,但是没有参与光照计算,看起来和Mobile Diffuse有区 ...
- OpenGL中的光照技术(翻译)
Lighting:https://www.evl.uic.edu/julian/cs488/2005-11-03/index.html 光照 OpenGL中的光照(Linghting)是很重要的,为什 ...
- Deferred Shading,延迟渲染(提高渲染效率,减少多余光照计算)【转】
Deferred Shading,看过<Gems2> 的应该都了解了.最近很火的星际2就是使用了Deferred Shading. 原帖位置: http://blog.csdn.net ...
- Opengl场景中加光照包含几个步骤
http://zuoye.baidu.com/question/44e2a82d7ad5c0e1d33ddb9a40e0bf86.html Opengl场景中加光照包含几个步骤,各个步骤实现用的函数 ...
- Shader 中的颜色计算
下面介绍 Shader 中 gl_FragColor 的计算与转换: 一.颜色计算 1. 加 这里要讲讲三原色和三基色:三原色一般指的是红.绿.蓝三种,简称 RGB,这是加色系.就是光源只含有特定的波 ...
随机推荐
- 【Linux】系统之vmstat&iostat
Linux系统出现了性能问题,一般我们可以通过top.iostat.free.vmstat等命令来查看初步定位问题. iostat常见用法: $iostat -d -k 1 10 #查看TPS和吞吐量 ...
- linux内存文件系统之指南
内存文件系统使用及示例:ramdisk, ramfs, tmpfs 第一部分在Linux中可以将一部分内存mount为分区来使用,通常称之为RamDisk. RamDisk有三种实现方式: 第一种就是 ...
- 黄聪:Discuz!X/数据库操作方法、DB::table、C::t
函数 功能 DB::table($tablename) 获取正确带前缀的表名,转换数据库句柄, DB::delete($tablename, 条件,条数限制) 删除表中的数据 DB::insert($ ...
- (VS) TFS lost mapping suddenly.
家里的网络不是很稳定.今天突然发现 TFS 上所有的 mapping都突然没有了. 尝试去remapping,在Source Control Explorer 中右击源文件,然后选择 Advanced ...
- jetty-run运行报错的原因
- mysql5.6优化建议
这篇文章主要介绍了MySQL5.6基本优化配置,详细分解了MySQL5.6需要优化的配置项,最终给出了一个优化案例,需要的朋友可以参考下 随着 大量默认选项的改进, MySQL 5.6比以前版 ...
- php 信号量
一些理论基础: 信号量:又称为信号灯.旗语 用来解决进程(线程同步的问题),类似于一把锁,访问前获取锁(获取不到则等待),访问后释放锁. 临界资源:每次仅允许一个进程访问的资源. 临界区:每个进程中访 ...
- ice介绍 z
什么是ICE(Internet Communications Engine)呢,它是由Zeroc公司开 发的一套开源中间件系统,与DCOM,CORBA,WEB SERVICEDcom类似,支持RPC( ...
- Android 开发中常用 ADB 命令总结
adb 的全称为 Android Debug Bridge,就是起到调试桥的作用.通过 adb 我们可以在 Eclipse 中方便通过 DDMS 来调试 Android 程序,说白了就是 debug ...
- proxmox3.2安装FreeBSD或者FreeNAS注意事项
别的不多说了,白般尝试,终于安装成功,原来硬件要如下设置才行,如下: 1)内存要开大点,512M 800M都不行,最后开导2G才可以,如下: 2)kvm硬件虚拟化一定要选择“否”,默认是“是”,这里 ...