openGL CG 系列教程2 - Vertex Lighting

*原创文章,转载请注明出处*

openGL CG 系列教程2

vertex lighting

 

之前的一篇教程HelloCG介绍了Cg的一些最基本的东西。这篇教程将介绍利用可编程渲染管线来实现光照。光照模型将采用广泛应用的phong模型,虽然这种模型在openGL的固定管线中已经实现了,但是学习该光照模型可以更加清楚的了解可编程渲染管线的流程。

 

首先要实现phong光照模型先要了解该模型中光照计算,关于phong模型光照计算的相关资料网上相当多,或者参考任何一本计算机图形学的相关书籍即可,这里只给出计算公式。

 

C = ambient + diffuse + specular

 

从公式中可以得出,物体顶点的最终颜色是由环境反射,漫反射和镜面反射三个成分来决定的。环境反射的计算公式为:

 

ambient = IaKa

 

其中,Ia是光的环境反射强度,Ka是物体材质的环境射系数。环境反射很简单,和光源、法线等等都没有关系,下面是只有环境反射的例子。

 

 

Fig1环境反射,Ia=(1.0, 1.0, 1.0)Ka=(0.15,0.15,0.0)

 

和环境反射相比,漫反射就稍微复杂一点,它和光源的位置和物体顶点的法线都有关系。漫反射的计算公式为:

 

diffuse = I­d­Kd (NL)

 

其中I­d­是光的漫反射强度,Kd是物体材质漫反射系数,NL表示法线N和入射光线L的内积。下面是只有面反射的例子。

 

 

Fig2漫反射,Id=(1.0, 1.0, 1.0)Kd=(1.0, 1.0 , 0.0)

 

最后是镜面反射,和漫反射相比,镜面反射又复杂了一点。它不仅和光源位置,物体顶点法线有关系,而且还和我们观看的位置有关系。镜面反射的计算公式为:

 

specular = IsKs(VR)­n

 

其中Is是光的镜面反射强度,Ks是物体材质的镜面反射系数,VR表示相机朝向向量V和反射光线R的内积,n表示该内积的n次幂。这里反射光线R可以通过公式

 

R = 2(LN)N-L­

 

来得到。这里还可以使用half vector来计算,计算half vector要比计算反射向量R方便快速的多。

 

H=(L+V)/2

 

所以,镜面反射公式现在可以写成

 

specular = IsKs(NH)­n

 

下面是只有镜面反射的例子。

 

 

 

Fig3镜面反射,Is=(1.0, 1.0, 1.0)Ks=(1.0, 1.0 , 1.0,), n=32

通过上面的过程,分别计算出了物体每个顶点的环境反射,面反射和镜面反射。最后简单将这三个成分相加即可得到顶点最终的颜色。

 

C = IaKa + I­d­Kd (NL)+ IsKs(NH)­n

 

fig4显示了这个相加的过程。

 

+

+

=

Fig4 phong光照

 

下面是vertex shader的代码。由于是基于vertex的光照,所以不需要fragment shader

 

02vs.cg

uniform float3 LightPosition; //光源位置

uniform float3 eyePosition;   //相机位置

uniform float3 I;              //光强度

uniform float3 Ka;             //环境光反射系数

uniform float3 Kd;             //漫反射系数

uniform float3 Ks;             //镜面反射系数

uniform float shininess;      //n幂次

 

struct output

{

      float4 position : POSITION; 

      float4 color     : COLOR; 

};

 

output vs_main( float4 position : POSITION,

                     float3 normal   : NORMAL,

                     uniform float4x4 MV, // 在相机坐标系中计算,所以要用到ModelView变换矩阵

                     uniform float4x4 MVP // ModelViewProjection变换矩阵

                    )

{

      output OUT;

      OUT.position = mul(MVP, position);

 

      float3 N = normalize(mul(MV, float4(normal,0.0)) ).xyz; //转换法线到相机坐标系

      float3 P = mul(MV, position).xyz; //转换物体顶点到相机坐标系

 

      float3 L = normalize(LightPosition - P);

      float NdotL = max(dot(N,L),0); //判断法线和入射光线的角度是否大于90

 

      float3 ambient = Ka * I; //环境反射

      float3 diffuse = Kd * I * NdotL; //漫反射

 

      float3 V = normalize(eyePosition - P);

      float3 H = normalize(L+V); //half vector

      float NdotH = pow(max(dot(N,H), 0), shininess);

      if(NdotL<=0) NdotH = 0.0;

 

      float3 specular = Ks*I*NdotH; //镜面反射

 

      float3 color = ambient + diffuse +specular; //所有成分相加

      OUT.color.xyz= color;

      OUT.color.w = 1.0;

 

      return OUT;

}

*原创文章,转载请注明出处*

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张赐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值