网页功能: 加入收藏 设为首页 网站搜索  
Shader 分析之 - Hatching(阴影线)
发表日期:2007-03-28作者:[转贴] 出处:  
 


Shader 分析之 - Hatching(阴影线)


原文出处:
格式问题,观看不清楚,请点这里看原文:
http://www.azure.com.cn/article.asp?id=283

如有转载,请注明:
http://www.azure.com.cn

效果图如下:

此例子作为NPR渲染的经典例子,对理解实现NPR渲染的方法,很有指导作用。
实现此效果需要两个pass
[list]
[*]PASS1: 绘制内部的阴影线
[*]PASS2: 绘制外部轮廓线
[/list]

首先来说PASS1,
PASS1中需要一个vertex shader和pixel shader , 代码如下:

vertex shader:


uniform vec4 lightDir;

varying vec2 vTexCoord;
varying vec3 vHatchWeights0;
varying vec3 vHatchWeights1;

void main(void) 
{
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
   vTexCoord = vec2(gl_MultiTexCoord0);

   vec3 posW    = gl_NormalMatrix * gl_Vertex.xyz;
   vec3 normalW = normalize(gl_NormalMatrix * gl_Normal);

   float  diffuse = min(1.0,max(0.0,dot(lightDir.xyz,normalW)));
   diffuse = diffuse * diffuse;
   diffuse = diffuse * diffuse;

   float  hatchFactor = diffuse * 6.0;
   vec3 weight0 = vec3(0.0);
   vec3 weight1 = vec3(0.0);

   if (hatchFactor>5.0)
   {
      weight0.x = 1.0;
   } // End if

   else if (hatchFactor>4.0)
   {
      weight0.x = 1.0 - (5.0 - hatchFactor);
      weight0.y = 1.0 - weight0.x;
   } // End else if

   else if (hatchFactor>3.0)
   {
      weight0.y = 1.0 - (4.0 - hatchFactor);
      weight0.z = 1.0 - weight0.y;
   } // End else if

   else if (hatchFactor>2.0)
   {
      weight0.z = 1.0 - (3.0 - hatchFactor);
      weight1.x = 1.0 - weight0.z;
   } // End else if

   else if (hatchFactor>1.0)
   {
      weight1.x = 1.0 - (2.0 - hatchFactor);
      weight1.y = 1.0 - weight1.x;
   } // End else if

   else if (hatchFactor>0.0)
   {
      weight1.y = 1.0 - (1.0 - hatchFactor);
      weight1.z = 1.0 - weight1.y;
   } // End else if

   vHatchWeights0 = weight0;
   vHatchWeights1 = weight1;

   
}
[/code]

pixel shader:
[code]
uniform sampler2D Hatch0;
uniform sampler2D Hatch1;
uniform sampler2D Hatch2;
uniform sampler2D Hatch3;
uniform sampler2D Hatch4;
uniform sampler2D Hatch5;
varying vec2 vTexCoord;
varying vec3 vHatchWeights0;
varying vec3 vHatchWeights1;

void main(void)
{
    vec4 hatchTex0 = texture2D(Hatch0,vTexCoord) * vHatchWeights0.x;
    vec4 hatchTex1 = texture2D(Hatch1,vTexCoord) * vHatchWeights0.y;
    vec4 hatchTex2 = texture2D(Hatch2,vTexCoord) * vHatchWeights0.z;
    vec4 hatchTex3 = texture2D(Hatch3,vTexCoord) * vHatchWeights1.x;
    vec4 hatchTex4 = texture2D(Hatch4,vTexCoord) * vHatchWeights1.y;
    vec4 hatchTex5 = texture2D(Hatch5,vTexCoord) * vHatchWeights1.z;
    
    
    vec4 hatchColor = hatchTex0 +
                        hatchTex1 +
                        hatchTex2 +
                        hatchTex3 +
                        hatchTex4 +
                        hatchTex5;
                        
     gl_FragColor = hatchColor;
  
}
[/code]

我们实现hatching需要多张hatching纹理,
这些hatching是一系列又淡到浓的素描纹理,如下:

在VS中。我们通过 N dot L 算出了此顶点的受光亮度,如下
[code]
   float  diffuse = min(1.0,max(0.0,dot(lightDir.xyz,normalW)));
   diffuse = diffuse * diffuse;
   diffuse = diffuse * diffuse;
[/code]
后面把diffuse平方两次是为了,把亮度降低点,把整体亮度向暗方向偏移,
这里只是为了更好的视觉效果。

现在最关键的就是要通过这个亮度值决定使用哪些hatch纹理的权重(hatch0, hatch1, hatch2, hatch3, hatch4, hatch5)
在这里为了减少vs向ps插值变量个数,巧妙使用了两个vec3来记录每个hatch图所绘制的权重,
见以下代码:
[code]
   float  hatchFactor = diffuse * 6.0;
   vec3 weight0 = vec3(0.0);
   vec3 weight1 = vec3(0.0);

   if (hatchFactor>5.0)
   {
      weight0.x = 1.0;
   } // End if

   else if (hatchFactor>4.0)
   {
      weight0.x = 1.0 - (5.0 - hatchFactor);
      weight0.y = 1.0 - weight0.x;
   } // End else if

   else if (hatchFactor>3.0)
   {
      weight0.y = 1.0 - (4.0 - hatchFactor);
      weight0.z = 1.0 - weight0.y;
   } // End else if

   else if (hatchFactor>2.0)
   {
      weight0.z = 1.0 - (3.0 - hatchFactor);
      weight1.x = 1.0 - weight0.z;
   } // End else if

   else if (hatchFactor>1.0)
   {
      weight1.x = 1.0 - (2.0 - hatchFactor);
      weight1.y = 1.0 - weight1.x;
   } // End else if

   else if (hatchFactor>0.0)
   {
      weight1.y = 1.0 - (1.0 - hatchFactor);
      weight1.z = 1.0 - weight1.y;
   } // End else if

   vHatchWeights0 = weight0;
   vHatchWeights1 = weight1;
[/code]
首先diffuse值被乘以6,是为了好方便区分区段。
下面一系列判断就是判断diffuse值到底在哪个区段里面,
以决定相应的权重。
 vHatchWeights0.x 对应hatch0 的权重
 vHatchWeights0.y 对应hatch1 的权重
 vHatchWeights0.z 对应hatch2 的权重
 vHatchWeights1.x 对应hatch3 的权重
 vHatchWeights1.y 对应hatch4 的权重
 vHatchWeights1.z 对应hatch5 的权重

接下来vHatchWeights0, vHatchWeight1 被插值到了ps
后面就很简单了,根据相应的权重,取得相应纹理的颜色,再合成起来。
代码如下:
 [code]  vec4 hatchTex0 = texture2D(Hatch0,vTexCoord) * vHatchWeights0.x;
    vec4 hatchTex1 = texture2D(Hatch1,vTexCoord) * vHatchWeights0.y;
    vec4 hatchTex2 = texture2D(Hatch2,vTexCoord) * vHatchWeights0.z;
    vec4 hatchTex3 = texture2D(Hatch3,vTexCoord) * vHatchWeights1.x;
    vec4 hatchTex4 = texture2D(Hatch4,vTexCoord) * vHatchWeights1.y;
    vec4 hatchTex5 = texture2D(Hatch5,vTexCoord) * vHatchWeights1.z;
    
    
    vec4 hatchColor = hatchTex0 +
                        hatchTex1 +
                        hatchTex2 +
                        hatchTex3 +
                        hatchTex4 +
                        hatchTex5;


此时pass1完成了。

PASS2 绘制外部轮廓线:
其实很简单,就是将原来的模型,以背面剔除的方式,线框模式,再绘制一遍,
你可以设置适当线宽。

最后效果就出来了。

我来说两句】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 Shader 分析之 - Hatching(阴影线)
本类热点文章
  DDraw和D3D立即模式编程手册
  矩阵求逆的快速算法
  本地化支持:OGRE+CEGUI中文输入:OGRE方..
  Direct3D中实现图元的鼠标拾取
  3D场景中的圆形天空顶
  OpenGL显卡编程
  一种高效的基于大规模地形场景的OCCLUS..
  一个完善的读取3DS文件例子
  如何制作一个可控制的人体骨骼模型
  Direct3D 入门之我见
  Slope(斜坡) 法线生成算法,在地形渲染..
  在Direct3D中渲染文字
最新分类信息我要发布 
最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放  
Copyright ©2003-2024 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00539