Normal based Edge Dtect

2015-05-19  本文已影响0人  ShiweyYan

边缘检测有很多方法,这里讲的是基于法线的边缘检测。

需要的知识有RTT(Render to target),嗯,没错就这么简单,你只要会RTT,两分钟就搞定这个算法。

这个算法的核心思想就是利用物体的边缘法线会发生变化,而法线变化越大,两个法线点积的值就越小。
那么如何获取法线呢,这里就涉及到了RTT,你要将需要检测的物体先渲染一遍,将法线信息保存到一张纹理中,然后通过采样对比每一点的法线和它周围的法线,从而得到结果。

具体步骤

1.RTT,将法线保存到一张纹理中。

2.使用一中的纹理,采用获得其中的法线数据,并将每一点的法线和它周围像素的法线点积,这样就可以得到一张描边的纹理了。

3.根据需求使用上边那张纹理。

具体实现:

步骤1的实现:

VertexOut VS(VertexIn vin)
{
    VertexOut vout;

    // 转换到投影空间
    vout.PosH = mul(float4(vin.PosL, 1.0f), World);
    vout.PosH = mul(vout.PosH, View);
    vout.PosH = mul(vout.PosV, Proj);

    vout.NormalV = mul(float4(vin.Normal,0.0f), WorldInvTransView).xyz;

    return vout;
}

float4 PS(VertexOut pin) : SV_Target
{
    pin.NormalV = normalize(pin.NormalV);

    float4 normal = float4(pin.NormalV,0.0f);

    return normal;
}

步骤2的实现:

vs就不写了,看你具体干什么了直接说ps:

float4 PS_EdgeDetect(VertexOut pin) : SV_Target
{
    float3 normal = normalDepthTex.Sample(samNormalDepth, pin.Tex).xyz;
    float sum = 0;
    if (normal.x!=0.f&&normal.y!=0.f&&normal.z!=0.f)
    {
        for (int i = 0; i < 4; ++i)
        {
            sum += saturate(1 - dot(normal, normalDepthTex.Sample(samNormalDepth, pin.Tex + PixelKernel[i]).xyz));
        }
    }
    
    return float4(sum, sum, sum, 0.0f);
}

大致就是这样,具体的需要根据具体需求去更改。

下面按照惯例上图:

edge_detectedge_detect
上一篇 下一篇

猜你喜欢

热点阅读