经典光照模型(illumination model)

物体表面光照颜色由入射光、物体材质,以及材质和光的交互规律共同决定。

由于环境光给予物体各个点的光照强度相同,且没有方向之分,所以在只有环境光的情况下,同一物体各点的明暗程度均一样。

环境光是对光照现象的最简单抽象,局限性很大。它仅能描述光线在空间中无方向并均匀散布时的状态。

还有一种是平行光,即光线都从同一个方向照射。通过模拟方向光和物体表面的交互模式,可以渲染出具有高真实感(明暗变化、镜面反射等)的三维场景。

漫反射与Lambert 模型

粗糙的物体表面向各个方向等强度地反射光,这种等同地向各个方向散射的现象称为光的漫反射(diffuse reflection)

对于仅暴露在环境光下的朗伯反射体,可以用公式(9-1)表示某点处漫反射的光强:

其中Ia表示环境光强度(简称光强),dk(0<dk<1)为材质对环境光的反射系数,Iam是漫反射体与环境光交互反射的光强。

当方向光照射到朗伯反射体上时,漫反射光的光强与入射光的方向和入射点表面法向夹角的余弦成正比,这称之为Lambert 定律,并由此构造出Lambert漫反射模型:

I是点光源强度,θ是入射光方向与顶点法线的夹角,称为入射(0≤θ ≤90°)

若N 为顶点单位法向量,L 表示从顶点指向光源的单位向量(注意,是由顶点指向光源,不要弄反了),则cosθ 等价于N 与L 的点积。所以公式(9-2)可以表示为公式(9-3):

综合考虑环境光和方向来,Lambert 光照模型可写为:

漫反射渲染

漫反射光照模型顶点着色程序(使用结构体)

  1. struct VertexIn
  2. {
  3. float4 position : POSITION;
  4. float4 normal : NORMAL;
  5. };
  6. struct VertexScreen
  7. {
  8. float4 oPosition : POSITION;
  9. float4 color : COLOR;
  10. };
  11. void main_v(VertexIn posIn,
  12. out VertexScreen posOut,
  13. uniform float4x4 modelViewProj,
  14. uniform float4x4 worldMatrix,
  15. uniform float4x4 worldMatrix_IT,
  16. uniform float3 globalAmbient,
  17. uniform float3 lightPosition,
  18. uniform float3 lightColor,
  19. uniform float3 Kd)
  20. {
  21. posOut.oPosition = mul(modelViewProj, posIn.position);
  22. float3 worldPos = mul(worldMatrix, posIn.position).xyz;
  23. float3 N = mul(worldMatrix_IT, posIn.normal).xyz;
  24. N = normalize(N);
  25. //计算入射光方向
  26. float3 L = lightPosition - worldPos;
  27. L = normalize(L);
  28. //计算方向光漫反射光强
  29. float3 diffuseColor = Kd*lightColor*max(dot(N, L), 0);
  30. //计算环境光漫反射光强
  31. float3 ambientColor = Kd*globalAmbient;
  32. posOut.color.xyz = diffuseColor+ambientColor;
  33. posOut.color.w = 1;
  34. }

镜面反射与Phong 模型

Lambert 模型较好地表现了粗糙表面上的光照现象,但表现不出光泽,主要原因是该模型没有考虑这些表面的镜面反射效果。

Phong Bui Tuong 提出一个计算镜面反射光强的经验模型,称为phong模型,认为镜面反射的光强与反射光线和视线的夹角相关,其数学表达如公式(9-5)所示:

k 为材质的镜面反射系数, Ns是高光指数,V表示从顶点到视点的观察方向, R代表反射光方向。

高光指数反映了物体表面的光泽程度。Ns越大,反射光越集中,当偏离反射方向时,光线衰减的越厉害,只有当视线方向与反射光线方向非常接近时才能看到镜面反射的高光现象,此时,镜面反射光将会在反射方向附近形成亮且小的光斑; Ns越小,表示物体越粗糙,反射光分散,观察到的光斑区域小,强度弱。

反射光的方向R 可以通过入射光方向L(从顶点指向光源)和物体法向量N求出:

phong 模型渲染

phong 光照模型的顶点着色程序实现

  1. struct VertexIn
  2. {
  3. float4 position : POSITION; // Vertex in object-space
  4. float4 normal : NORMAL;
  5. };
  6. struct VertexScreen
  7. {
  8. float4 oPosition : POSITION;
  9. float4 color : COLOR;
  10. };
  11. void main_v( VertexIn posIn,
  12. out VertexScreen posOut,
  13. uniform float4x4 modelViewProj,
  14. uniform float4x4 worldMatrix,
  15. uniform float4x4 worldMatrix_IT,
  16. uniform float3 globalAmbient,
  17. uniform float3 eyePosition,
  18. uniform float3 lightPosition,
  19. uniform float3 lightColor,
  20. uniform float3 Kd,
  21. uniform float3 Ks,
  22. uniform float shininess)
  23. {
  24. posOut.oPosition = mul(modelViewProj, posIn.position);
  25. float3 worldPos = mul(worldMatrix, posIn.position).xyz;
  26. float3 N = mul(worldMatrix_IT, posIn.normal).xyz;
  27. N = normalize(N);
  28. //计算入射光方向、视线方向、反射光线方向
  29. float3 L = normalize(lightPosition - worldPos);
  30. float3 V = normalize(eyePosition - worldPos);
  31. float3 R = 2*max(dot(N, L), 0)*N-L;
  32. R = normalize(R);
  33. // 计算漫反射分量
  34. float3 diffuseColor = Kd * globalAmbient+Kd*lightColor*max(dot(N, L), 0);
  35. //计算镜面反射分量
  36. float3 specularColor = Ks * lightColor*pow(max(dot(V, R), 0), shininess);
  37. posOut.color.xyz = diffuseColor + specularColor;
  38. posOut.color.w = 1;
  39. }

phong 光照模型片段着色实现的结构体

  1. struct VertexIn
  2. {
  3. float4 position : POSITION;
  4. float4 normal : NORMAL;
  5. };
  6. struct VertexScreen
  7. {
  8. float4 oPosition : POSITION;
  9. float4 objectPos : TEXCOORD0;
  10. float4 objectNormal : TEXCOORD1;
  11. };

首先将几何顶点的模型空间坐标转换为用于光栅化的投影坐标;然后将顶点模型坐标和法向量模型坐标赋值给绑定TEXCOORD 语义词的变量,用于传递到片段着色程序中。

phong 光照模型顶点着色程序

  1. void main_v(VertexIn posIn,
  2. out VertexScreen posOut,
  3. uniform float4x4 modelViewProj)
  4. {
  5. posOut.oPosition = mul(modelViewProj, posIn.position);
  6. posOut.objectPos = posIn.position;
  7. posOut.objectNormal = posIn.normal;
  8. }

phong 光照模型片段着色程序

  1. void main_f( VertexScreen posIn,
  2. out float4 color : COLOR,
  3. uniform float4x4 worldMatrix,
  4. uniform float4x4 worldMatrix_IT,
  5. uniform float3 globalAmbient,
  6. uniform float3 eyePosition,
  7. uniform float3 lightPosition,
  8. uniform float3 lightColor,
  9. uniform float3 Kd,
  10. uniform float3 Ks,
  11. uniform float shininess)
  12. {
  13. float3 worldPos = mul(worldMatrix, posIn.objectPos).xyz;
  14. float3 N = mul(worldMatrix_IT, posIn.objectNormal).xyz;
  15. N = normalize(N);
  16. //计算入射光方向、视线方向、反射光线方向
  17. float3 L = normalize(lightPosition - worldPos);
  18. float3 V = normalize(eyePosition - worldPos);
  19. float3 R = 2*max(dot(N, L), 0)*N-L;
  20. R = normalize(R);
  21. // 计算漫反射分量
  22. float3 diffuseColor = Kd * globalAmbient+Kd*lightColor*max(dot(N, L), 0);
  23. //计算镜面反射分量
  24. float3 specularColor = Ks * lightColor*pow(max(dot(V, R), 0), shininess);
  25. color.xyz = diffuseColor + specularColor;
  26. color.w = 1;
  27. }

Blinn-Phong 光照模型

phong光照模型中,必须计算V • R的值,其中R为反射光线方向单位向量,V 为视线方向单位向量,但是在Blinn-phong光照模型中,用N • H 的值取代了V • R。Blinn-phong光照模型公式为:

H 是“光入射方向L 和视点方向V 的中间向量”,通常也称之为半角向量。

Blinn-phong 模型片段着色程序

  1. void main_f(VertexScreen posIn,
  2. out float4 color : COLOR,
  3. uniform float4x4 worldMatrix,
  4. uniform float4x4 worldMatrix_IT,
  5. uniform float3 globalAmbient,
  6. uniform float3 eyePosition,
  7. uniform float3 lightPosition,
  8. uniform float3 lightColor,
  9. uniform float3 Kd,
  10. uniform float3 Ks,
  11. uniform float shininess)
  12. {
  13. float3 worldPos = mul(worldMatrix, posIn.objectPos).xyz;
  14. float3 N = mul(worldMatrix_IT, posIn.objectNormal).xyz;
  15. N = normalize(N);
  16. //计算入射光方向/视线方向/半角向量
  17. float3 L = normalize(lightPosition - worldPos);
  18. float3 V = normalize(eyePosition - worldPos);
  19. float3 H = normalize(L + V);
  20. // 计算漫反射分量
  21. float3 diffuseColor = Kd * globalAmbient+Kd*lightColor*max(dot(N, L), 0);
  22. //计算镜面反射分量
  23. float3 specularColor = Ks * lightColor*pow(max(dot(N, H), 0), shininess);
  24. color.xyz = diffuseColor + specularColor;
  25. color.w = 1;
  26. }

http://blog.csdn.net/doctorsc/article/details/6287059?reload

(转)光照模型及cg实现的更多相关文章

  1. [CG编程] 基本光照模型的实现与拓展以及常见光照模型解析

    0.前言 这篇文章写于去年的暑假.大二的假期时间多,小组便开发一个手机游戏的项目,开发过程中忙里偷闲地了解了Unity的shader编写,而CG又与shaderLab相似,所以又阅读了<CG教程 ...

  2. CG之基本光照模型计算公式

    在一个基本模型里,一个物体表面的颜色是由放射(emissive).环境反射(ambient).漫反射(diffuse)和镜面反射(specular)等光照作用的总和.每种光照作用取决于表面材质的性质( ...

  3. 解读Unity中的CG编写Shader系列八(镜面反射)

    转自http://www.itnose.net/detail/6117378.html 讨论完漫反射之后,接下来肯定就是镜面反射了 在开始镜面反射shader的coding之前,要扩充一下前面提到的知 ...

  4. Unity3D ShaderLab 自定义光照模型

    接着上一篇BasicMyDiffuse的代码来说,这次要说明的就是自定义的光照模型,Ctrl+D>BasicMyDiffuse. 1.>//#pragma surface surf Lam ...

  5. 【Unity Shaders】使用CgInclude让你的Shader模块化——创建CgInclude文件存储光照模型

    本系列主要參考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同一时候会加上一点个人理解或拓展. 这里是本书全部的插图. 这里是本书所需的代码 ...

  6. 【Unity Shaders】Lighting Models —— 光照模型之Lit Sphere

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  7. 【Unity Shaders】Diffuse Shading——创建一个自定义的diffuse lighting model(漫反射光照模型)

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  8. Unity shader学习之高光反射光照模型

    高光反射光照模型的公式如下: Cspecular = Clight * mspecular * max(0, dot(v, r))gloss 要计算高光反射需要知道4个参数:入射光线颜色Cspecul ...

  9. Phong和Blinn-Phong光照模型

    Phong和Blinn-Phong是计算镜面反射光的两种光照模型,两者仅仅有很小的不同之处. 1.Phong模型 Phone模型计算中的一个关键步骤就是反射向量R的计算: 上图中的位于表面“下面”的向 ...

随机推荐

  1. MBIST:用于嵌入式存储器的可测试设计技术

    MBist技术可以自动实现存储器单元或阵列的RTL级内建自测试电路,MBIST的EDA工具支持多种测试算法的自动实现,可针对一个或多个内嵌存储器自动创建BIST逻辑,并完成BIST逻辑与存储器的连接, ...

  2. Java生成指定范围内的工具类

    /** * 生成[min, max]之间的随机整数 * * @param min 最小整数 * @param max 最大整数 * @return * @author jqlin */ private ...

  3. lucene源码分析(8)MergeScheduler

    1.使用IndexWriter.java mergeScheduler.merge(this, MergeTrigger.EXPLICIT, newMergesFound); 2.定义MergeSch ...

  4. unity简单动画实现

    1:创建一个Sprite Render (player)的动画对象并添加脚本Player,点击主菜单“Window(视窗)→Animation(动画窗口)”Animation面板(选中需要动画的对象) ...

  5. hadoop2.x学习笔记(一):YARN

    一.YARN产生的背景 MapReduce1.x存在的问题:单点故障&节点压力大不易扩展. 资源利用率&成本 催生了YARN的诞生  不同计算框架可以共享同一个HDFS集群上的数据,享 ...

  6. api.closeFrame

    关闭frame closeFrame({params}) params name: 类型:字符串 默认值:无 描述:(可选项)frame 名字,不传时关闭当前 frame 示例代码 api.close ...

  7. BASE64转文件下载

    你可以用HTML 5 注意:返回的文件数据必须是base 64编码的,因为您不能对二进制数据进行JSON编码 在我的AJAX我得到了如下的数据结构: <!DOCTYPE html> < ...

  8. Angular建立待办事项应用

    建立路由 接前一小节,在src/app/app.component.html把login组件去掉 第一步: 在src/index.html指定基准路径 浏览器会根据这个路径下载css,图像,js文件, ...

  9. Struts2 学习笔记--Action Method--接收参数

    struts2中的路径问题 注意:在jsp中”/”表示tomcat服务器的根目录,在struts.xml配置文件中”/”表示webapp的根路径,即MyEclipse web项目中的WebRoot路径 ...

  10. [日常] GO语言圣经-并发获取多个URL

    go语言圣经-并发获取多个URL 1.GO最新奇的特性就是对并发编程的支持,goroutine和channel 2.goroutine是一种函数的并发执行方式,而channel是用来在goroutin ...