游戏开发论坛

 找回密码
 立即注册
搜索
查看: 7386|回复: 3

Shader 分析之 - Hatching(阴影线)

[复制链接]

32

主题

1259

帖子

1351

积分

金牌会员

Rank: 6Rank: 6

积分
1351
发表于 2007-2-5 21:12:00 | 显示全部楼层 |阅读模式
原文出处:
格式问题,观看不清楚,请点这里看原文:
http://www.azure.com.cn/article.asp?id=283



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

效果图如下:



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


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

vertex shader:

  1. uniform vec4 lightDir;

  2. varying vec2 vTexCoord;
  3. varying vec3 vHatchWeights0;
  4. varying vec3 vHatchWeights1;

  5. void main(void)
  6. {
  7.    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
  8.    vTexCoord = vec2(gl_MultiTexCoord0);

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

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

  14.    float  hatchFactor = diffuse * 6.0;
  15.    vec3 weight0 = vec3(0.0);
  16.    vec3 weight1 = vec3(0.0);

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

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

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

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

  36.    else if (hatchFactor>1.0)
  37.    {
  38.       weight1.x = 1.0 - (2.0 - hatchFactor);
  39.       weight1.y = 1.0 - weight1.x;
  40.    } // End else if

  41.    else if (hatchFactor>0.0)
  42.    {
  43.       weight1.y = 1.0 - (1.0 - hatchFactor);
  44.       weight1.z = 1.0 - weight1.y;
  45.    } // End else if

  46.    vHatchWeights0 = weight0;
  47.    vHatchWeights1 = weight1;

  48.    
  49. }
复制代码


pixel shader:

  1. uniform sampler2D Hatch0;
  2. uniform sampler2D Hatch1;
  3. uniform sampler2D Hatch2;
  4. uniform sampler2D Hatch3;
  5. uniform sampler2D Hatch4;
  6. uniform sampler2D Hatch5;
  7. varying vec2 vTexCoord;
  8. varying vec3 vHatchWeights0;
  9. varying vec3 vHatchWeights1;

  10. void main(void)
  11. {
  12.     vec4 hatchTex0 = texture2D(Hatch0,vTexCoord) * vHatchWeights0.x;
  13.     vec4 hatchTex1 = texture2D(Hatch1,vTexCoord) * vHatchWeights0.y;
  14.     vec4 hatchTex2 = texture2D(Hatch2,vTexCoord) * vHatchWeights0.z;
  15.     vec4 hatchTex3 = texture2D(Hatch3,vTexCoord) * vHatchWeights1.x;
  16.     vec4 hatchTex4 = texture2D(Hatch4,vTexCoord) * vHatchWeights1.y;
  17.     vec4 hatchTex5 = texture2D(Hatch5,vTexCoord) * vHatchWeights1.z;
  18.    
  19.    
  20.     vec4 hatchColor = hatchTex0 +
  21.                         hatchTex1 +
  22.                         hatchTex2 +
  23.                         hatchTex3 +
  24.                         hatchTex4 +
  25.                         hatchTex5;
  26.                         
  27.      gl_FragColor = hatchColor;
  28.   
  29. }
复制代码


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


在VS中。我们通过 N dot L 算出了此顶点的受光亮度,如下

  1.    float  diffuse = min(1.0,max(0.0,dot(lightDir.xyz,normalW)));
  2.    diffuse = diffuse * diffuse;
  3.    diffuse = diffuse * diffuse;
复制代码

后面把diffuse平方两次是为了,把亮度降低点,把整体亮度向暗方向偏移,
这里只是为了更好的视觉效果。

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

  1.    float  hatchFactor = diffuse * 6.0;
  2.    vec3 weight0 = vec3(0.0);
  3.    vec3 weight1 = vec3(0.0);

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

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

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

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

  23.    else if (hatchFactor>1.0)
  24.    {
  25.       weight1.x = 1.0 - (2.0 - hatchFactor);
  26.       weight1.y = 1.0 - weight1.x;
  27.    } // End else if

  28.    else if (hatchFactor>0.0)
  29.    {
  30.       weight1.y = 1.0 - (1.0 - hatchFactor);
  31.       weight1.z = 1.0 - weight1.y;
  32.    } // End else if

  33.    vHatchWeights0 = weight0;
  34.    vHatchWeights1 = weight1;
复制代码

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

接下来vHatchWeights0, vHatchWeight1 被插值到了ps
后面就很简单了,根据相应的权重,取得相应纹理的颜色,再合成起来。
代码如下:
  1.   vec4 hatchTex0 = texture2D(Hatch0,vTexCoord) * vHatchWeights0.x;
  2.     vec4 hatchTex1 = texture2D(Hatch1,vTexCoord) * vHatchWeights0.y;
  3.     vec4 hatchTex2 = texture2D(Hatch2,vTexCoord) * vHatchWeights0.z;
  4.     vec4 hatchTex3 = texture2D(Hatch3,vTexCoord) * vHatchWeights1.x;
  5.     vec4 hatchTex4 = texture2D(Hatch4,vTexCoord) * vHatchWeights1.y;
  6.     vec4 hatchTex5 = texture2D(Hatch5,vTexCoord) * vHatchWeights1.z;
  7.    
  8.    
  9.     vec4 hatchColor = hatchTex0 +
  10.                         hatchTex1 +
  11.                         hatchTex2 +
  12.                         hatchTex3 +
  13.                         hatchTex4 +
  14.                         hatchTex5;
复制代码


此时pass1完成了。

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

最后效果就出来了。

www.azure.com.cn

59

主题

984

帖子

1200

积分

金牌会员

Rank: 6Rank: 6

积分
1200
发表于 2007-2-6 01:38:00 | 显示全部楼层

Re:Shader 分析之 - Hatching(阴影线)

啊,效果不错
不过if else太多了,不知道性能如何
看了一下还有很大优化空间
把条件测试改为1D纹理查找应该会更快
另外轮廓线都是灰度图的情况下,可以把多张纹理打包为一张^^

顶一下~~

414

主题

611

帖子

621

积分

高级会员

Rank: 4

积分
621
发表于 2007-2-6 17:10:00 | 显示全部楼层

Re: Shader 分析之 - Hatching(阴影线)

hatching texture要如何?生呢?不同的texture要可以接和要花一些工夫.
???一下,有完整的project??可以放上???

32

主题

1259

帖子

1351

积分

金牌会员

Rank: 6Rank: 6

积分
1351
 楼主| 发表于 2007-2-6 17:26:00 | 显示全部楼层

Re:Shader 分析之 - Hatching(阴影线)

不需要,接合 ,
是程序插值来过渡的
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-26 10:40

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表