openGL CG3-Pixel Lighting

本文详细介绍了如何使用Cg语言实现基于像素光照的PhongShading技术,通过对比FlatShading、GouraudShading和PhongShading的不同效果,展示了在fragment shader中计算光照的方法,并提供了完整的Cg shader代码示例。

在上一篇教程中介绍了phong model下的一般光照,并且用Cg着色语言实现了固定渲染管线中gouraud shading光照效果。由于是基于vertex的光照,虽然采用gouraud shading要比flat shading效果好的多,但是和phong shading的效果相差很大。这里大家要注意的是,phong model和phong shading的区别。上一篇教程所讲的光照模型叫phong model,而这篇教程要介绍的一种着色方法叫phong shading,必须要使用shader才能实现。下面的图中对比了采用flat shading,gouraud shading和phong shading技术渲染的一个圆环。

1

有了上一篇教程的基础,用Cg来实现基于pixel lighing的phong shading光照就容易多了。绝大部分的Cg shader代码都是一样的,主要的改变就是这次不是在vertex shader里光照,而是在fragment shader里计算光照。所以整个vertex shader的代码很简单,将要渲染的物体的顶点位置,顶点法线传入fragment shader就是vertex shader的全部工作。整个vertex shader的代码如下。

03vs.cg


  
  1. struct output  
  2. {  
  3.       float4 position  : POSITION;      
  4.       float3 objectPos : TEXCOORD0;     
  5.       float3 normal     : TEXCOORD1;  
  6. };  
  7.    
  8. output vs_main( float4 position : POSITION,  
  9.                   float3 normal   : NORMAL,  
  10.                   uniform float4x4 MV,  
  11.                   uniform float4x4 MVP  
  12.                     )  
  13. {  
  14.       output OUT;  
  15.       OUT.position = mul(MVP, position);  
  16.       OUT.objectPos = mul(MV, position).xyz;  
  17.       OUT.normal = mul(MV, float4(normal,0.0)).xyz;  
  18.    
  19.       return OUT;  
  20. }  

上面的代码的输出结构体中有三个成员。Position是传入的物体的顶点,该顶点将用ModelViewProjection矩阵转换成剪裁坐标系中的坐标供光栅化使用。一旦将坐标转换后,我们就无法在fragment shader中使用物体的顶点坐标了。由于要在fragment shader中计算光照,所以我们要将物体的顶点位置,顶点法线都传入到fragment shader中。这里物体转换前的顶点和法线分别使用了语义TEXCOORD0和TEXCOORD1,代表将它们作为纹理坐标后传入fragment shader。这样GPU会把顶点和法线信息当做纹理坐标来处理,在贴图的时候,GPU会根据纹理自动插值计算每个像素对应的颜色,而现在GPU插值计算出来的就是每个像素对应的坐标和法线信息了。有了这些数据就可以进行phong shading的计算了。光照计算的公式和方法和上一个教程介绍的一模一样。下面是fragment shader的代码。

03fs.cg

  
  1. uniform float3 LightPosition;  
  2. uniform float3 eyePosition;  
  3. uniform float3 I;  
  4. uniform float3 Ka;  
  5. uniform float3 Kd;  
  6. uniform float3 Ks;  
  7. uniform float shininess;  
  8.    
  9. struct input{  
  10.       float3 objectPos: TEXCOORD0;     
  11.       float3 normal   : TEXCOORD1;  
  12. };  
  13.    
  14. struct output{  
  15.       float4 color     : COLOR;  
  16. };  
  17.    
  18. output fs_main( in input IN )  
  19. {  
  20.       output OUT;  
  21.    
  22.       float3 N = normalize(IN.normal);  
  23.       float3 P = IN.objectPos;  
  24.    
  25.       float3 L = normalize(LightPosition - P);  
  26.       float NdotL = max(dot(N,L),0);  
  27.    
  28.       float3 ambient = Ka * I;  
  29.       float3 diffuse = Kd * I * NdotL;  
  30.    
  31.       float3 V = normalize(eyePosition - P);  
  32.       float3 H = normalize(L+V);  
  33.       float NdotH = pow(max(dot(N,H), 0), shininess);  
  34.    
  35.       if(NdotL<=0)  
  36.            NdotH = 0.0;  
  37.       float3 specular = Ks*I*NdotH;  
  38.    
  39.       float3 color = ambient + diffuse + specular;  
  40.       OUT.color.xyz= color;  
  41.       OUT.color.w = 1.0;  
  42.    
  43.       return OUT;  
  44. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值