第9章 phong光照模型
- 格式:ppt
- 大小:2.50 MB
- 文档页数:62
Phong光照模型的Shader实现计算反射向量Phong⽤到的是反射向量,计算反射向量的公式是R = 2*N(dot(N, L)) - L这个公式是根据向量的投影公式以及平⾏四边形法则推导出来的详细步骤请看这篇⽂章,讲的⾮常好Shader "Phong"{Properties{_MainTex ("Texture", 2D) = "white" {}_Specular("Specular", Range(1, 20)) = 1_SpecColor("SpecColor", Color) = (1,1,1,1)}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;float3 normal : TEXCOORD1;float3 lightDir : TEXCOORD2;float4 objPos : TEXCOORD3;};sampler2D _MainTex;float4 _MainTex_ST;float4 _LightColor0;float _Specular;float4 _SpecColor;v2f vert (appdata_full v){v2f o;o.objPos = v.vertex;o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);o.normal = v.normal;o.lightDir = ObjSpaceLightDir(v.vertex);//把光向量从世界空间转成模型空间return o;}fixed4 frag (v2f i) : SV_Target{float3 L = normalize(i.lightDir);float3 N = normalize(i.normal);float3 viewDir = normalize(ObjSpaceViewDir(i.objPos));//计算出视线float diff = saturate(dot(L, N));float3 reflection = normalize(2.0 * N * diff - L);//反射向量float spec = pow(max(0, dot(reflection, viewDir)), _Specular);float3 finalSpec = _SpecColor.rgb * spec;//漫反射+镜⾯⾼光+环境光float3 finalLight = diff * _LightColor0 + finalSpec + UNITY_LIGHTMODEL_AMBIENT;fixed4 col = tex2D(_MainTex, i.uv);return col * float4(finalLight, 1);}ENDCG}}}Blinn-phong光照模型blinn是⼀个⼈的名字,他叫吉姆·布林,图形学界的⼤⽜,他发现了使⽤半⾓向量代替反射向量的计算⽅式原理是通过视线向量跟光向量的半⾓向量代替反射向量halfVector = normalize( L + V );/herox25000/article/details/50491483在图形学中,计算光照模型时,经常需要求取反射向量,⼀般的shader函数库都提供计算反射向量的⽅法,下⾯介绍⼀下如何⼿动计算反射向量。
Unityshader学习之Blinn-Phong光照模型Blinn-Phong光照模型不⽤计算反射⽅向,计算公式如下:h = normalize(v + l);C specular = C light * m specular * pow(max(0, dot(n, h), gloss))转载请注明出处:shader如下:1 Shader "Custom/Specular Blinn-Phong"2 {3 Properties4 {5 _Diffuse ("Diffuse Color", Color) = (1,1,1,1)6 _Specular ("Specular Color", Color) = (1,1,1,1)7 _Gloss ("Gloss", Range(8, 256)) = 88 }9 SubShader10 {11 Tags { "RenderType"="Opaque" }12 LOD 1001314 Pass15 {16 Tags { "LightMode"="ForwardBase" }1718 CGPROGRAM19#pragma vertex vert20#pragma fragment frag2122 #include "UnityCG.cginc"23 #include "Lighting.cginc"2425struct appdata26 {27 float4 vertex : POSITION;28 float3 normal : NORMAL;29 };3031struct v2f32 {33 float4 vertex : SV_POSITION;34 float3 worldPos : TEXCOORD0;35 float3 worldNormal : TEXCOORD1;36 };3738 fixed4 _Diffuse;39 fixed4 _Specular;40float _Gloss;4142 v2f vert (appdata v)43 {44 v2f o;45 o.vertex = UnityObjectToClipPos(v.vertex);46 o.worldNormal = UnityObjectToWorldNormal(v.normal);47 o.worldPos = mul(unity_ObjectToWorld, v.vertex);48return o;49 }5051 fixed4 frag (v2f i) : SV_Target52 {53// specular54 float3 worldNormal = normalize(i.worldNormal);55 float3 lightDir = UnityWorldSpaceLightDir(i.worldPos);56 lightDir = normalize(lightDir);57 float3 viewDir = UnityWorldSpaceViewDir(i.worldPos);58 viewDir = normalize(viewDir);59 float3 halfDir = normalize(lightDir + viewDir);60float d = max(0, dot(halfDir, worldNormal));61 float3 spec = _LightColor0.rgb * _Specular.rgb * pow(d, _Gloss);6263// diffuse64 float3 diff = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(lightDir, worldNormal));6566 float3 c = spec + diff + UNITY_LIGHTMODEL_AMBIENT.rgb;67return fixed4(c, 1);68 }69 ENDCG70 }71 }72 }效果如下:这种光照模型的⾼光反射看起来更⼤,更亮⼀些。
计算机图形学课程实验:Phong模型目录1 Phong模型 (1)1.1 光源设置 (1)2 光照计算 (3)2.1 定向光 (3)2.2 点光源 (4)2.3 聚光 (4)1 Phong模型接下来,我们来介绍一下Phong模型。
绘制效果如下,我们可以看到,中间的立方体是被照射的对象,有一个定向光源,六个点光源和一个聚光的光源。
图1 效果图我们的程序流程主体还是跟前面的课程相同。
因此我们这节的重点部分就是主要在这两个方面,一个是光源的设置,一个是光照计算。
1.1 光源设置首先是光源的设置,我们这里的光源种类主要有三种,定向光,点光源和聚光,三种光源的效果叠加形成了我们刚才看到的效果。
那么我们在代码中是如何实现的呢?首先我们来看定向光,定向光就是类似太阳这种,它的属性包括定向光的方向,以及环境光,漫反射光,镜面反射光的强度参数。
由于定向光是光源处于无限远处的平行光,因此我们无需指定出定向光光源具体的位置,只需指定其指向的方向即可。
接下来是点光源,我们定义了六个点光源,点光源就是类似灯泡这种,每一个点光源的属性都包括点光源的位置,环境光,漫反射光,和镜面反射光的1强度参数,这里每一个分量都要乘一个点光源的颜色。
那么除此之外点光源与定向光有哪些不同呢?它与定向光不同的是它多了三个属性参数,这三个参数是用来计算衰减公式的三个系数,分别是constant常数项,linear一次项和quadratic二次项,它会使得光线强度随距离的增加不断减小并且衰减的幅度也逐渐减小,这样更接近现实生活中点光源的效果。
我们的第三种光源是聚光,聚光就是类似手电筒的这种效果,聚光的属性也包括聚光光源的位置,方向,这里我们是用摄像机的位置和朝向来指定的,还有环境光,漫反射光,和镜面反射光的强度参数以及三个衰减系数,那么除此之外聚光光源与点光源又有哪些不同呢?这里我们又多了两个参数分别表示我们聚光内外圆锥的内外切光角。
聚光的效果就相当于是一个圆锥的光效,我们这里通过使用两个圆锥来使我们的聚光效果看起来更加平滑。
计算机图形学课程设计课程设计球体Phong光照模型一、实验目的(1)掌握双线性法矢插值模型;(2)掌握ZBuffer算法的思想;(3)掌握有效边表填充算法;二、实验要求1、建立三维坐标系Oxyz,原点位于屏幕客户区中心,x轴水平向右为正,y轴垂直向上为正,z轴垂直于屏幕指向观察者。
2、绘制体心和坐标系中心重合的球体表面,使用Z-Buffer消隐算法进行消隐。
3、使用单点光源对球体进行照射生成Phong光照模型,光源位置位于球体右上方。
4、背景色设置为RGB(128,0,0)。
5、使用键盘方向键旋转球体。
6、使用鼠标左击缩小球体、右击增大球体。
三、实验步骤建立球体的网格模型,使用地理划分法将球体北极和南极划分为三角形面片,其余部分划分为四边形面片,先对球体网格模型进行背面剔除,然后使用深度缓冲算法进行消隐。
计算面片各顶点的平均法矢量,然后采用双线性法失插值计算面片内各点的法矢量。
最终根据每点的法矢量对光源的朝向,通过简单光照模型计算所获得的光强。
面片使用有效边表算法填1、Phong双线性法矢插值模型Gouraud双线性光强插值模型解决了相邻多边形之间的颜色突变问题,产生的真实感图形颜色过渡均匀,图形显得非常光滑,这是它的优点,但是,由于采用光强插值,其镜面反射光效果不太理想,而且相邻多边形边界处的马赫带效应并不能完全消除。
Phong 模型提出的双线性法矢插值模型可以有效的解决上述问题,产生正确的高光区域。
Phong 模型在进行光强插值的时候,需要先对面片的每一个顶点计算平均法矢量,然后通过双线性法矢插值计算面片内每个点的法矢量,最后根据简单光照模型计算面片上各点的颜色值。
基本算法如下。
(1)计算面片顶点的平均法矢量。
∑∑===ni ini iNN N 11由于球心位于三维坐标系原点,所以球面上任意面片的顶点平均法矢量就是该点的位置矢量。
(2)计算面片内部各点的法矢量。
在图中,三角形面片的顶点坐标为),(000y x P ,法矢量为0N ;),,(111y x P 法矢量是1N ;。
Phong光照模型的简单说明我简单地介绍一下Phong光照模型...虽然这种光照模型算是比较古老的,但是通过合适的参数设置,仍然可以实现真实的效果。
我们的目标是渲染出以下效果,这里以Doom3的男主角为例(终于不是怪物了...)一般而言,Phong光照模型分为三个累加阶段:漫反射,镜面反射和环境光以下按顺序说明:1.漫反射(Diffuse)对于表面比较粗糙的物体,基本表面的明暗就是漫反射效果,比如裤子的材质。
某一个象素的明暗系数只取决于该点与光源的相对位置,而与眼睛的位置无关。
diffuse_color = base_map * (N * V_L )* mat_diffuse * light_diffuse;上式中base_map代表该点的基础颜色,一般通过纹理索引;N 是该点的法线;V_L是该点到光源方向的单位向量;N * V_L 即两者的点积,注意需要用max( ( N * V_L ), 0 ),因为负的值是没有意义的;mat_diffuse和light_diffuse分别是材质和光源的漫反射系数,用来宏观调制漫反射的颜色。
下图是只有N * V_L 项的渲染结果:2.镜面反射(Specular)尽管漫反射已经可以很好地表达光照,但是由于它是与视点无关的,所以多少有些欠缺生动,而镜面反射是视点相关的,所以会随着眼睛位置的变化而“流动”。
specular_color = pow( v_e' * v_l, gloss ) * mat_specular * light_specular;这里解释一下:v_e' 是e_v的反射向量(v_e' = reflect( e_v, n ) ),而e_v是眼睛到该点的单位向量,所谓反射向量,即以与该点的法线所垂直的平面做镜面反射所得到的向量(虽然按照原理来说,应该是光线反射,而非视线反射...都没有问题吧);v_l是该点到光源的单位向量;v_e' * v_l 是两者的点积, 同样要用max(v_e' * v_l,0),负的值也是不需要的;pow是幂积,点积是底,gloss是指数;gloss用来调制亮斑的大小,一般来说,gloss越大,光斑越细小,gloss越小,光斑分布越宽泛。