openGL CG 系列教程3-Pixel Lighting

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

 

openGL CG 系列教程3-Pixel Lighting

 

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

 

 

 

Flat shading

Gouraud shading

Phong shading

 

 

 

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

 

03vs.cg

struct output

{

      float4 position  : POSITION;    

      float3 objectPos : TEXCOORD0;   

      float3 normal     : TEXCOORD1;

};

 

output vs_main( float4 position : POSITION,

                  float3 normal   : NORMAL,

                  uniform float4x4 MV,

                  uniform float4x4 MVP

                    )

{

      output OUT;

      OUT.position = mul(MVP, position);

      OUT.objectPos = mul(MV, position).xyz;

      OUT.normal = mul(MV, float4(normal,0.0)).xyz;

 

      return OUT;

}

 

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

 

03fs.cg

uniform float3 LightPosition;

uniform float3 eyePosition;

uniform float3 I;

uniform float3 Ka;

uniform float3 Kd;

uniform float3 Ks;

uniform float shininess;

 

struct input{

      float3 objectPos: TEXCOORD0;   

      float3 normal   : TEXCOORD1;

};

 

struct output{

      float4 color     : COLOR;

};

 

output fs_main( in input IN )

{

      output OUT;

 

      float3 N = normalize(IN.normal);

      float3 P = IN.objectPos;

 

      float3 L = normalize(LightPosition - P);

      float NdotL = max(dot(N,L),0);

 

      float3 ambient = Ka * I;

      float3 diffuse = Kd * I * NdotL;

 

      float3 V = normalize(eyePosition - P);

      float3 H = normalize(L+V);

      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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

张赐

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

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

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

打赏作者

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

抵扣说明:

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

余额充值