(转)光照模型及cg实现
经典光照模型(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 光照模型可写为:

漫反射渲染
漫反射光照模型顶点着色程序(使用结构体)
- struct VertexIn
- {
- float4 position : POSITION;
- float4 normal : NORMAL;
- };
- struct VertexScreen
- {
- float4 oPosition : POSITION;
- float4 color : COLOR;
- };
- void main_v(VertexIn posIn,
- out VertexScreen posOut,
- uniform float4x4 modelViewProj,
- uniform float4x4 worldMatrix,
- uniform float4x4 worldMatrix_IT,
- uniform float3 globalAmbient,
- uniform float3 lightPosition,
- uniform float3 lightColor,
- uniform float3 Kd)
- {
- posOut.oPosition = mul(modelViewProj, posIn.position);
- float3 worldPos = mul(worldMatrix, posIn.position).xyz;
- float3 N = mul(worldMatrix_IT, posIn.normal).xyz;
- N = normalize(N);
- //计算入射光方向
- float3 L = lightPosition - worldPos;
- L = normalize(L);
- //计算方向光漫反射光强
- float3 diffuseColor = Kd*lightColor*max(dot(N, L), 0);
- //计算环境光漫反射光强
- float3 ambientColor = Kd*globalAmbient;
- posOut.color.xyz = diffuseColor+ambientColor;
- posOut.color.w = 1;
- }
镜面反射与Phong 模型
Lambert 模型较好地表现了粗糙表面上的光照现象,但表现不出光泽,主要原因是该模型没有考虑这些表面的镜面反射效果。

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

k 为材质的镜面反射系数, Ns是高光指数,V表示从顶点到视点的观察方向, R代表反射光方向。
高光指数反映了物体表面的光泽程度。Ns越大,反射光越集中,当偏离反射方向时,光线衰减的越厉害,只有当视线方向与反射光线方向非常接近时才能看到镜面反射的高光现象,此时,镜面反射光将会在反射方向附近形成亮且小的光斑; Ns越小,表示物体越粗糙,反射光分散,观察到的光斑区域小,强度弱。
反射光的方向R 可以通过入射光方向L(从顶点指向光源)和物体法向量N求出:


phong 模型渲染
phong 光照模型的顶点着色程序实现
- struct VertexIn
- {
- float4 position : POSITION; // Vertex in object-space
- float4 normal : NORMAL;
- };
- struct VertexScreen
- {
- float4 oPosition : POSITION;
- float4 color : COLOR;
- };
- void main_v( VertexIn posIn,
- out VertexScreen posOut,
- uniform float4x4 modelViewProj,
- uniform float4x4 worldMatrix,
- uniform float4x4 worldMatrix_IT,
- uniform float3 globalAmbient,
- uniform float3 eyePosition,
- uniform float3 lightPosition,
- uniform float3 lightColor,
- uniform float3 Kd,
- uniform float3 Ks,
- uniform float shininess)
- {
- posOut.oPosition = mul(modelViewProj, posIn.position);
- float3 worldPos = mul(worldMatrix, posIn.position).xyz;
- float3 N = mul(worldMatrix_IT, posIn.normal).xyz;
- N = normalize(N);
- //计算入射光方向、视线方向、反射光线方向
- float3 L = normalize(lightPosition - worldPos);
- float3 V = normalize(eyePosition - worldPos);
- float3 R = 2*max(dot(N, L), 0)*N-L;
- R = normalize(R);
- // 计算漫反射分量
- float3 diffuseColor = Kd * globalAmbient+Kd*lightColor*max(dot(N, L), 0);
- //计算镜面反射分量
- float3 specularColor = Ks * lightColor*pow(max(dot(V, R), 0), shininess);
- posOut.color.xyz = diffuseColor + specularColor;
- posOut.color.w = 1;
- }

phong 光照模型片段着色实现的结构体
- struct VertexIn
- {
- float4 position : POSITION;
- float4 normal : NORMAL;
- };
- struct VertexScreen
- {
- float4 oPosition : POSITION;
- float4 objectPos : TEXCOORD0;
- float4 objectNormal : TEXCOORD1;
- };
首先将几何顶点的模型空间坐标转换为用于光栅化的投影坐标;然后将顶点模型坐标和法向量模型坐标赋值给绑定TEXCOORD 语义词的变量,用于传递到片段着色程序中。
phong 光照模型顶点着色程序
- void main_v(VertexIn posIn,
- out VertexScreen posOut,
- uniform float4x4 modelViewProj)
- {
- posOut.oPosition = mul(modelViewProj, posIn.position);
- posOut.objectPos = posIn.position;
- posOut.objectNormal = posIn.normal;
- }
phong 光照模型片段着色程序
- void main_f( VertexScreen posIn,
- out float4 color : COLOR,
- uniform float4x4 worldMatrix,
- uniform float4x4 worldMatrix_IT,
- uniform float3 globalAmbient,
- uniform float3 eyePosition,
- uniform float3 lightPosition,
- uniform float3 lightColor,
- uniform float3 Kd,
- uniform float3 Ks,
- uniform float shininess)
- {
- float3 worldPos = mul(worldMatrix, posIn.objectPos).xyz;
- float3 N = mul(worldMatrix_IT, posIn.objectNormal).xyz;
- N = normalize(N);
- //计算入射光方向、视线方向、反射光线方向
- float3 L = normalize(lightPosition - worldPos);
- float3 V = normalize(eyePosition - worldPos);
- float3 R = 2*max(dot(N, L), 0)*N-L;
- R = normalize(R);
- // 计算漫反射分量
- float3 diffuseColor = Kd * globalAmbient+Kd*lightColor*max(dot(N, L), 0);
- //计算镜面反射分量
- float3 specularColor = Ks * lightColor*pow(max(dot(V, R), 0), shininess);
- color.xyz = diffuseColor + specularColor;
- color.w = 1;
- }

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

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

Blinn-phong 模型片段着色程序
- void main_f(VertexScreen posIn,
- out float4 color : COLOR,
- uniform float4x4 worldMatrix,
- uniform float4x4 worldMatrix_IT,
- uniform float3 globalAmbient,
- uniform float3 eyePosition,
- uniform float3 lightPosition,
- uniform float3 lightColor,
- uniform float3 Kd,
- uniform float3 Ks,
- uniform float shininess)
- {
- float3 worldPos = mul(worldMatrix, posIn.objectPos).xyz;
- float3 N = mul(worldMatrix_IT, posIn.objectNormal).xyz;
- N = normalize(N);
- //计算入射光方向/视线方向/半角向量
- float3 L = normalize(lightPosition - worldPos);
- float3 V = normalize(eyePosition - worldPos);
- float3 H = normalize(L + V);
- // 计算漫反射分量
- float3 diffuseColor = Kd * globalAmbient+Kd*lightColor*max(dot(N, L), 0);
- //计算镜面反射分量
- float3 specularColor = Ks * lightColor*pow(max(dot(N, H), 0), shininess);
- color.xyz = diffuseColor + specularColor;
- color.w = 1;
- }

http://blog.csdn.net/doctorsc/article/details/6287059?reload
(转)光照模型及cg实现的更多相关文章
- [CG编程] 基本光照模型的实现与拓展以及常见光照模型解析
0.前言 这篇文章写于去年的暑假.大二的假期时间多,小组便开发一个手机游戏的项目,开发过程中忙里偷闲地了解了Unity的shader编写,而CG又与shaderLab相似,所以又阅读了<CG教程 ...
- CG之基本光照模型计算公式
在一个基本模型里,一个物体表面的颜色是由放射(emissive).环境反射(ambient).漫反射(diffuse)和镜面反射(specular)等光照作用的总和.每种光照作用取决于表面材质的性质( ...
- 解读Unity中的CG编写Shader系列八(镜面反射)
转自http://www.itnose.net/detail/6117378.html 讨论完漫反射之后,接下来肯定就是镜面反射了 在开始镜面反射shader的coding之前,要扩充一下前面提到的知 ...
- Unity3D ShaderLab 自定义光照模型
接着上一篇BasicMyDiffuse的代码来说,这次要说明的就是自定义的光照模型,Ctrl+D>BasicMyDiffuse. 1.>//#pragma surface surf Lam ...
- 【Unity Shaders】使用CgInclude让你的Shader模块化——创建CgInclude文件存储光照模型
本系列主要參考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同一时候会加上一点个人理解或拓展. 这里是本书全部的插图. 这里是本书所需的代码 ...
- 【Unity Shaders】Lighting Models —— 光照模型之Lit Sphere
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- 【Unity Shaders】Diffuse Shading——创建一个自定义的diffuse lighting model(漫反射光照模型)
本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...
- Unity shader学习之高光反射光照模型
高光反射光照模型的公式如下: Cspecular = Clight * mspecular * max(0, dot(v, r))gloss 要计算高光反射需要知道4个参数:入射光线颜色Cspecul ...
- Phong和Blinn-Phong光照模型
Phong和Blinn-Phong是计算镜面反射光的两种光照模型,两者仅仅有很小的不同之处. 1.Phong模型 Phone模型计算中的一个关键步骤就是反射向量R的计算: 上图中的位于表面“下面”的向 ...
随机推荐
- ES6 笔记(二)- 总结
在最近进行的项目中,已经全面使用到ES6,这里对ES6进行整理总结.用得比较多的是带*的内容,这些语法.新增类型.模块调用等从代码量上.可读性上.操作上给项目带来了不少便利. 1.语法 1 ...
- 使用gitlab, jenkins搭建CI(持续集成)系统(2) -- 配置webhook触发构建
1. 在gitlab上配置192.168.1.30的ssh秘钥,使jenkins可以操作gitlab上的project 进入gitlab,点击右上角 点击 Settings -> SSH key ...
- bzoj 3600: 没有人的算术
Description Solution 我们可以给每一个数钦定一个权值 , 这样就可以 \(O(1)\) 比较大小了. 考虑怎么确定权值: 用平衡树来维护 , 我们假设根节点管辖 \([1,2^{6 ...
- Python---战机小游戏,学习pygame
import pygame # 导入游戏包 pygame.init() # 导入并初始化所有pygame模块,使用其他模块之前必须先调用init()方法 print('下面是游戏代码:') # 绘制矩 ...
- Ionic开发之如何修改Cordova插件
由于大多数的Cordova plugin都是国外的,一些提示信息通常都是英文, 这就需要我们自己修改成中文信息. 除此之外,还有可能插件的样式,皮肤等和整体项目的风格不一致,这个时候也是要修改的. 可 ...
- [转] What is a Full Stack developer?
期望一个凡人掌握开发过程中各个方面的知识,合理吗?也许不合理,但是Facebook正是要寻找这样的人.在一个OSCON会议上,一名Facebook的工程师告诉我的,他们只聘请“全能(Full stac ...
- 数据库导出Excel(转载)
来源:https://jingyan.baidu.com/article/3065b3b68f2ab7becef8a449.html SQLServer2005或者SQLServer2008.SQLS ...
- DBNull.Value 与null
来源:http://blog.csdn.net/beautifulsarah/article/details/54691670 DBNull.Value,, 适用于向数据库的表中插入空值.而 null ...
- 【模板】 全排列 && 有重复元素的全排列
全排列 #include<bits/stdc++.h> using namespace std; ]; void print (int n){ ;i<=n;i++) cout< ...
- [日常] Apache Order Deny,Allow的用法
Order Deny,Allow的用法:影响最终判断结果的只有两点:1. order语句中allow.deny的先后顺序,最后的是最优先的:2. allow.deny语句中各自包含的范围. 常用:Or ...