|
|
原文出处:
格式问题,观看不清楚,请点这里看原文:
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:
- 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;
-
- }
复制代码
pixel shader:
- 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;
-
- }
复制代码
我们实现hatching需要多张hatching纹理,
这些hatching是一系列又淡到浓的素描纹理,如下:

在VS中。我们通过 N dot L 算出了此顶点的受光亮度,如下
- float diffuse = min(1.0,max(0.0,dot(lightDir.xyz,normalW)));
- diffuse = diffuse * diffuse;
- diffuse = diffuse * diffuse;
复制代码
后面把diffuse平方两次是为了,把亮度降低点,把整体亮度向暗方向偏移,
这里只是为了更好的视觉效果。
现在最关键的就是要通过这个亮度值决定使用哪些hatch纹理的权重(hatch0, hatch1, hatch2, hatch3, hatch4, hatch5)
在这里为了减少vs向ps插值变量个数,巧妙使用了两个vec3来记录每个hatch图所绘制的权重,
见以下代码:
- 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;
复制代码
首先diffuse值被乘以6,是为了好方便区分区段。
下面一系列判断就是判断diffuse值到底在哪个区段里面,
以决定相应的权重。
vHatchWeights0.x 对应hatch0 的权重
vHatchWeights0.y 对应hatch1 的权重
vHatchWeights0.z 对应hatch2 的权重
vHatchWeights1.x 对应hatch3 的权重
vHatchWeights1.y 对应hatch4 的权重
vHatchWeights1.z 对应hatch5 的权重
接下来vHatchWeights0, vHatchWeight1 被插值到了ps
后面就很简单了,根据相应的权重,取得相应纹理的颜色,再合成起来。
代码如下:
- 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 绘制外部轮廓线:
其实很简单,就是将原来的模型,以背面剔除的方式,线框模式,再绘制一遍,
你可以设置适当线宽。
最后效果就出来了。
www.azure.com.cn
|
|