经典光照模型(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. 【持续更新】一个简洁、易用的美赛LaTeX模板: easyMCM

    目录 1 当前美赛模板通行情况的概述 2 easymcm宏包说明 2.1 与mcmthesis的关系之说明 2.2 easymcm宏包的简介 2.3 美赛模板下载地址 3 常见问题的解决方案 若您无意 ...

  2. Ionic3 UI组件之 ImageViewer

    组件特性: 轻触图片可全屏查看 手势上下滑动可关闭全屏查看 点击导航箭头可关闭视图 双击查看全图,并可放大 参考地址:https://github.com/Riron/ionic-img-viewer ...

  3. vps服务器搭建——Linode VPS 20美元优惠获取教程

    转载:http://www.cuishifeng.cn/linode/index.html?v=2 声明:本文旨在教大家怎么获得linode 20美元优惠,并免费使用4个月vps,请低调薅羊毛!(多张 ...

  4. THINK PHP 学习笔记20171115

    Part1:框架目录project 应用部署目录 ├─application 应用目录(可设置) │ ├─common 公共模块目录(可更改) │ ├─index 模块目录(可更改) │ │ ├─co ...

  5. 【转】HttpServletRequestWrapper 实现xss注入

    这里说下最近项目中我们的解决方案,主要用到commons-lang3-3.1.jar这个包的org.apache.commons.lang3.StringEscapeUtils.escapeHtml4 ...

  6. Java注解(二)

    前面了解了注解的基本内容,这次来看一下自定义注解. 自定义注解其实很简单,直接上代码: import java.lang.annotation.Documented; import java.lang ...

  7. 使用github搭建个人html网站

    前言:搭建个人网站早就想做了,最近有空就宅在家学习,突然发现github就可以搭建个人的纯html网站,于是开始了这项工作.转载请注明出处:https://www.cnblogs.com/yuxiao ...

  8. AGC006C Rabbit Exercise

    传送门 设 \(f_{i,j}\) 表示兔子 \(i\) 在当前 \(j\) 轮的期望位置 对于一次操作 \(f_{i,j+1}=\frac{1}{2}(2f_{i-1,j}-f_{i,j})+\fr ...

  9. 爬虫必备—scrapy-redis(分布式爬虫)

    转载自:http://www.cnblogs.com/wupeiqi/articles/6912807.html scrapy-redis是一个基于redis的scrapy组件,通过它可以快速实现简单 ...

  10. Redis在windows下安装过程(转载)

    转载自(http://www.cnblogs.com/M-LittleBird/p/5902850.html) 一.下载windows版本的Redis 官网以及没有下载地址,只能在github上下载, ...