当前位置: 代码迷 >> 综合 >> 【转】OpenGL CG系列教程2,vertex lighting
  详细解决方案

【转】OpenGL CG系列教程2,vertex lighting

热度:79   发布时间:2023-12-08 08:51:22.0

之前的一篇教程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 = IdKd (NL)

其中Id是光的漫反射强度,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可以通过公式

= 2(LN)N-L

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

specular = IsKs(NH)n

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

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

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

C = IaKa + IdKd (NL)IsKs(NH)n

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

Fig4 phong光照

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

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;

}
转自:http://blog.csdn.net/zhulinpptor/archive/2010/09/27/5909725.aspx