边缘高亮效果

游戏要实现模型的突出显示,最好是边缘高亮的效果.刚听到这个东西时,第一个进入头脑中的就是:边缘检测.于是就写了一个:
<tbody>

    <tr>

        <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">

        <div>Pass 0:</div>

        <div>渲染模型到一个RenderTarget Model上,并把模型的形状写入Alpha通道.</div>

        <div>Pass 1:</div>

        <div>对上面得到的Alpha通道用拉普拉斯模板进行滤波,得到一个边缘,写入另一个RenderTarget Edge.</div>

        <div>Pass 2:</div>

        <div>把前面得到的两个RenderTarget进行合成,输出到屏幕.</div>

        </td>

    </tr>

</tbody>
 
虽说效果还不错,但是用掉了两个RenderTarget,显然不合算.而且,用拉普拉斯在PixelShader中进行逐像素的处理,效率并不高.
 
阿来在GameDev上求得另一种方法:把模型画两遍,其中一次对模型进行一次放大,关闭Z-Write就出来这种效果了.不过有两个问题:
一是模型直接放缩是以模型坐标系的原点来的,而这个原点并不一定是在模型的中心.就算在中心,对于一些非凸多面体并不能得到很好的效果,有一些边缘会被模型遮住.
二是,关闭了深度检测,那这个模型怎么跟别的模型来进行遮挡处理呢?
 
后来在群里有人提醒说在3D游戏程序设计入门这本书上有,我才想起来有一个卡通渲染的例子.卡通渲染?那里面不也有轮廓生成吗?看了一下书上的实现方法,用的是三角形退化,有点复杂.于是google之,发现了一个跟GameDev上那个方法差不多思想的:
<tbody>

    <tr>

        <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">

        <div>Pass0:</div>

        <div>把模型按法线方向进行放大,然后渲染成单色模型,不过只渲染背面,避免遮住正常的模型.(把D3DRS_CULLMODE设成D3DCULL_CW就可以了)</div>

        <div>Pass1:</div>

        <div>正常渲染模型,不用做什么改变.不过不要忘了把D3DRS_CULLMODE改回来.</div>

        </td>

    </tr>

</tbody>
 
Shader:
<tbody>

    <tr>

        <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">

        <div><span style="color: blue">float4x4</span> matViewProjection;</div>

        <div>&nbsp;</div>

        <div><span style="color: blue">struct</span> VS_INPUT </div>

        <div>{</div>

        <div><span>&nbsp;&nbsp; <span style="color: blue">float4</span> Position : <span style="color: fuchsia">POSITION0</span>;</span></div>

        <div style="margin-left: 21pt; text-indent: -21pt"><span>&nbsp;&nbsp; <span style="color: blue">float3</span> Normal&nbsp;&nbsp; : <span style="color: fuchsia">NORMAL0</span>;</span></div>

        <div>};</div>

        <div>&nbsp;</div>

        <div><span style="color: blue">struct</span> VS_OUTPUT </div>

        <div>{</div>

        <div><span>&nbsp;&nbsp; <span style="color: blue">float4</span> Position : POSITION0;</span></div>

        <div>};</div>

        <div>&nbsp;</div>

        <div>VS_OUTPUT vs_main( VS_INPUT Input )</div>

        <div>{</div>

        <div><span>&nbsp;&nbsp; VS_OUTPUT Output;</span></div>

        <div>&nbsp;</div>

        <div style="margin-left: 21pt; text-indent: -21pt"><span>&nbsp;&nbsp; Output.Position = <span style="color: blue">float4</span>(Input.Position.xyz + Input.Normal*0.4f,1);</span></div>

        <div><span>&nbsp;&nbsp; Output.Position = <span style="color: red">mul</span>( Output.Position, matViewProjection );</span></div>

        <div>&nbsp;</div>

        <div style="margin-left: 21pt; text-indent: -21pt"><span>&nbsp;&nbsp; <span style="color: blue">return</span>( Output );</span></div>

        <div>}</div>

        </td>

    </tr>

    <tr>

        <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 426.1pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="568">

        <div><span style="color: blue">sampler2D</span> BaseMap;</div>

        <div>&nbsp;</div>

        <div><span style="color: blue">float4</span> ps_main() : <span style="color: fuchsia">COLOR0</span></div>

        <div>{</div>

        <div><span>&nbsp;&nbsp; <span style="color: blue">return</span> <span style="color: blue">float4</span>(0, 1, 0, 1);</span></div>

        <div>}</div>

        </td>

    </tr>

</tbody>
 
下面是两种方法实现的效果对比:
差不多哈,区别就是用卡通渲染的那种方法出来的中间也有轮廓线.
 

a