关闭

openGL CG 系列教程3-Pixel Lighting

标签: floatshaderoutputinputstruct语言
3964人阅读 评论(1) 收藏 举报
分类:

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

 

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
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:183046次
    • 积分:2301
    • 等级:
    • 排名:第17277名
    • 原创:30篇
    • 转载:0篇
    • 译文:0篇
    • 评论:226条
    最新评论