使用GLSL实现更多数量的局部光照 【转】
原文 http://www.cnblogs.com/CGDeveloper/archive/2008/07/02/1233816.html
众所周知,OpenGL固定管线只提供了最多8盏灯光。如何使得自己的场景之中拥有更多的灯光效果呢?
这里提供一种使用GLSL shader实现更多数量的局部光照。
在GLSL里,首先建立光照参数数据结构:
struct myLightParams
{
bool enabled;
vec4 position;
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec3 spotDirection;
float spotCutoff;
float spotExponent;
float constantAttenuation;
float linearAttenuation;
float quadraticAttenuation;
};
然后,需要app传入的参数:
const int maxLightCount = 32;
uniform myLightParams light[maxLightCount];
uniform bool bLocalViewer;
uniform bool bSeperateSpecualr;
主函数:
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
vec4 pos = gl_ModelViewMatrix * gl_Vertex;
vec3 epos = vec3(pos)/pos.w;
vec3 normal = normalize(gl_NormalMatrix * gl_Normal);
vec3 eye;
if (bLocalViewer)
eye = -normalize(epos);
else
eye = vec3(0, 0, 1.0);
vec4 amb = vec4(0);
vec4 diff = vec4(0);
vec4 spec = vec4(0);
for (int i=0; i<maxLightCount; i++)
{
if (light[i].enabled == false)
continue;
if (light[i].position.w == 0)
{
DirectionalLight(i, eye, epos, normal, amb, diff, spec);
}
else if (light[i].spotCutoff == 180.0)
{
PointLight(i, eye, epos, normal, amb, diff, spec);
}
else
{
SpotLight(i, eye, epos, normal, amb, diff, spec);
}
}
vec4 color = gl_FrontLightModelProduct.sceneColor +
amb * gl_FrontMaterial.ambient +
diff * gl_FrontMaterial.diffuse;
if (bSeperateSpecualr)
{
gl_FrontSecondaryColor = spec * gl_FrontMaterial.specular;
}
else
{
gl_FrontSecondaryColor = vec4(0, 0, 0, 1.0);
color += spec * gl_FrontMaterial.specular;
}
gl_FrontColor = color;
}
对于方向光源的计算:
void DirectionalLight(int i, vec3 eye, vec3 epos, vec3 normal,
inout vec4 amb, inout vec4 diff, inout vec4 spec)
{
float dotVP = max(0, dot(normal, normalize(vec3(light[i].position))));
float dotHV = max(0, dot(normal, normalize(eye+normalize(vec3(light[i].position)))));
amb += light[i].ambient;
diff += light[i].diffuse * dotVP;
spec += light[i].specular * pow(dotHV, gl_FrontMaterial.shininess);
}
对于点光源:
void PointLight(int i, vec3 eye, vec3 epos, vec3 normal,
inout vec4 amb, inout vec4 diff, inout vec4 spec)
{
vec3 VP = vec3(light[i].position) - epos;
float d = length(VP);
VP = normalize(VP);
float att = 1.0/(light[i].constantAttenuation + light[i].linearAttenuation*d + light[i].quadraticAttenuation*d*d);
vec3 h = normalize(VP+eye);
float dotVP = max(0, dot(normal, VP));
float dotHV = max(0, dot(normal, h));
amb += light[i].ambient * att;
diff += light[i].diffuse * dotVP * att;
spec += light[i].specular * pow(dotHV, gl_FrontMaterial.shininess) * att;
}
对于聚光灯:
void SpotLight(int i, vec3 eye, vec3 epos, vec3 normal,
inout vec4 amb, inout vec4 diff, inout vec4 spec)
{
vec3 VP = vec3(light[i].position) - epos;
float d = length(VP);
VP = normalize(VP);
float att = 1.0/(light[i].constantAttenuation + light[i].linearAttenuation*d + light[i].quadraticAttenuation*d*d);
float dotSpot = dot(-VP, normalize(light[i].spotDirection));
float cosCutoff = cos(light[i].spotCutoff*3.1415926/180.0);
float spotAtt = 0;
if (dotSpot < cosCutoff)
spotAtt = 0;
else
spotAtt = pow(dotSpot, light[i].spotExponent);
att *= spotAtt;
vec3 h = normalize(VP+eye);
float dotVP = max(0, dot(normal, VP));
float dotHV = max(0, dot(normal, h));
amb += light[i].ambient * att;
diff += light[i].diffuse * dotVP * att;
spec += light[i].specular * pow(dotHV, gl_FrontMaterial.shininess) * att;
}
这样,对于场景之中的任意对象,它所能够接受计算的光源就可以突破8个的限制了。
上述光照计算是遵循OpenGL spec的,因此与固定管线的效果是一致的。
使用GLSL实现更多数量的局部光照 【转】的更多相关文章
- Deferred Shading,延迟渲染(提高渲染效率,减少多余光照计算)【转】
Deferred Shading,看过<Gems2> 的应该都了解了.最近很火的星际2就是使用了Deferred Shading. 原帖位置: http://blog.csdn.net ...
- Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第八章:光照
原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第八章:光照 代码工程地址: https://github.com/j ...
- Obj模型功能完善(物体材质,光照,法线贴图).Cg着色语言+OpenTK+F#实现.
这篇文章给大家讲Obj模型里一些基本功能的完善,包含Cg着色语言,矩阵转换,光照,多重纹理,法线贴图的运用. 在上篇中,我们用GLSL实现了基本的phong光照,这里用Cg着色语言来实现另一钟Blin ...
- JNI/NDK开发指南(十)——JNI局部引用、全局引用和弱全局引用
转自:http://blog.csdn.net/xyang81/article/details/44657385 这篇文章比较偏理论,详细介绍了在编写本地代码时三种引用的使用场景和注意事项.可能看 ...
- WebGL学习笔记(八):光照
局部光照与全局光照 局部光照 只考虑光源到模型表面的照射效果,运算量较小: 全局光照 考虑到环境中所有表面和光源相互作用的照射效果,即让没有直接受光照射的位置也会受周围反射光的影响,运算量较大: Ph ...
- 最大化 AIX 上的 Java 性能,第 3 部分: 更多就是更好
http://www.ibm.com/developerworks/cn/aix/library/es-Javaperf/es-Javaperf3.html 最大化 AIX 上的 Java 性能,第 ...
- 【翻译】Jay Kreps - 为何流处理中局部状态是必要的
译者注: 原文作者是 Jay Kreps,也是那篇著名的<The Log: What every software engineer should know about real-time da ...
- [Swift]LeetCode775. 全局倒置与局部倒置 | Global and Local Inversions
We have some permutation Aof [0, 1, ..., N - 1], where N is the length of A. The number of (global) ...
- matlab练习程序(局部加权线性回归)
通常我们使用的最小二乘都需要预先设定一个模型,然后通过最小二乘方法解出模型的系数. 而大多数情况是我们是不知道这个模型的,比如这篇博客中z=ax^2+by^2+cxy+dx+ey+f 这样的模型. 局 ...
随机推荐
- VS2010使用EventHandler发邮件
转:http://blog.csdn.net/alfred_72/article/details/9980279 因为不知道VS2010 Sharepoint 有EventReciver这个添加项,走 ...
- POJ 2481 Cows
Cows Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 16546 Accepted: 5531 Description ...
- C# delegate 学习 (练这么久终于悟出来点东东了,继续加油! ^_^)
前言 从事开发工作两年有余了,但还是对Delegate,Event神马的看见就头疼,文章看过无数,自己也练习过好多遍,但到用的时候或者人家换了一种形式之后就又不懂了,哎~智商捉急啊!! 但是,这两天的 ...
- Filezilla中文字符文件看不到或显示乱码的解决办法
Filezilla确实是跨平台的好软件,可之前我就在ubuntu下郁闷为什么看坛子FTP里竟然是空的.最近换MAC版的FZ结果还是这样就奇怪了. 后来想Filezilla应该是支持字符集转换的,所以在 ...
- SQL Server缺省约束、列约束和表约束
SQL Server缺省约束是SQL Server数据库中的一种约束,下面就为您介绍SQL Server缺省约束.列约束和表约束的定义方法啊,供您参考. SQL Server缺省约束 SQL Serv ...
- qt 获取天气的接口
博客来源:http://blog.csdn.net/lzqwebsoft/article/details/7054045 网站api接口:http://smart.weather.com.cn/wzf ...
- 多校1005 HDU5785 Interesting (manacher)
// 多校1005 HDU5785 Interesting // 题意:给你一个串,求相邻两个回文串左边端点*右边端点的和 // 思路:马拉车算出最长回文半径,求一个前缀和,既得到每个点对答案的贡献. ...
- Java-note-输入流
java不像C中拥有scanf这样功能强大的函数,大多是通过定义输入输出流对象.常用的类有BufferedReader,Scanner.实例程序:一,利用 Scanner 实现从键盘读入integer ...
- Python学习笔记——正则表达式
今天把之前学的正则表达式好好总结总结. 一.元字符 . : .表示可以匹配任意一个字符 \d : \d表示可以匹配任意一个数字 \D : \D表示可以匹配任意一个非数字 \s : \s表示 ...
- [HIve - LanguageManual] Joins
Hive Joins Hive Joins Join Syntax Examples MapJoin Restrictions Join Optimization Predicate Pushdown ...