zoukankan      html  css  js  c++  java
  • Qt 3D研究(九):尝试第二边缘检测方法

    Qt 3D研究(九):尝试第二边缘检测方法

           三维应用程序,通过FBO。将3D图像渲染成纹理,然后对渲染成的纹理进行图像处理,终于显示在屏幕上的。是风格化后的图案。上一次我使用了一种普通的图像处理方法:索贝尔边缘检測法,与我们的卡通渲染结合起来,实现了这种效果。接着。我将採用第二种边缘检測方法——普雷维特(Prewitt)边缘检測方法来又一次渲染图案。

    蒋彩阳原创文章。首发地址:http://blog.csdn.net/gamesdev/article/details/44405219。

    欢迎同行前来探讨。

           首先让我们看看上一次的截图:

           我们看到,本不应该是边缘的机身部分。因为离散的调色,被索贝尔算子边缘检測一算,也被误觉得是边缘了,同一时候,在背景与机身颜色不明显的部分,也因为採用不适当的阈值,不被觉得是边缘。

    所以我想有没有一种方法可以解决问题呢?于是我採取了这个方案:

    1、 第一遍的render pass,取的不是卡通着色的颜色图,而是深度图。

    2、 将深度图渲染至纹理;

    3、 对该纹理进行边缘检測;

    4、 与卡通着色的图进行叠加,做成效果图。

    怎样在GLSL中将片元的深度信息提取出来?这里我參考了前辈的博客,然后写出了这种GLSL代码:

    // Depth.vert
    #version 100
    
    // Qt 3D默认提供的參数
    attribute vec3 vertexPosition;
    uniform mat4 modelView;
    uniform mat4 mvp;
    
    void main( void )
    {
        gl_Position = mvp * vec4( vertexPosition, 1.0 );
    }
    
    // Depth.frag
    #version 110
    
    // 自己提供的參数
    
    bool inBetween( float v, float min, float max )
    {
        return v > min && v < max;
    }
    
    void main( void )
    {
        float exp = 256.0;
        gl_FragColor = vec4( vec3( pow( gl_FragCoord.z, exp ) ), 1.0);
    }

           由于gl_FragCoord.z表示的片元深度信息相互之间很接近。我们须要一个指数乘幂操作将这种差别放大,这样才干区分不同的深度的值。

           紧接着,我们将Prewitt算子替换掉Sobel算子,终于的着色器代码例如以下:

    // Ouput.vert
    #version 100
    
    // Qt 3D默认提供的參数
    attribute vec4 vertexPosition;
    uniform mat4 modelMatrix;
    
    // 自己提供的參数
    
    void main( void )
    {
        gl_Position = modelMatrix * vertexPosition;
    }
    
    // Output.frag
    #version 100
    
    // 自己提供的參数
    uniform sampler2D colorAttachTex;
    //uniform sampler2D depthAttachTex;
    uniform vec2 texSize;
    uniform float texOffsetX;
    uniform float texOffsetY;
    
    float gray( vec4 color )
    {
        return dot( color.xyz, vec3( 0.299, 0.587, 0.114 ) );
    }
    
    void main( void )
    {
        vec4 texColor[9];
        texColor[0] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( -texOffsetX, texOffsetY ) );
        texColor[1] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( 0.0, -texOffsetY ) );
        texColor[2] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( texOffsetX, texOffsetY ) );
        texColor[3] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( -texOffsetX, 0 ) );
        texColor[4] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( 0.0, 0.0 ) );
        texColor[5] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( texOffsetX, 0 ) );
        texColor[6] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( -texOffsetX, -texOffsetY ) );
        texColor[7] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( 0.0, -texOffsetY ) );
        texColor[8] = texture2D( colorAttachTex, gl_FragCoord.xy / texSize + vec2( texOffsetX, -texOffsetY ) );
    
        // 普雷维特算子
        float prewitt_x[9];
        prewitt_x[0] = -1.0;
        prewitt_x[1] = 0.0;
        prewitt_x[2] = 1.0;
        prewitt_x[3] = -1.0;
        prewitt_x[4] = 0.0;
        prewitt_x[5] = 1.0;
        prewitt_x[6] = -1.0;
        prewitt_x[7] = 0.0;
        prewitt_x[8] = 1.0;
    
        float prewitt_y[9];
        prewitt_y[0] = 1.0;
        prewitt_y[1] = 1.0;
        prewitt_y[2] = 1.0;
        prewitt_y[3] = 0.0;
        prewitt_y[4] = 0.0;
        prewitt_y[5] = 0.0;
        prewitt_y[6] = -1.0;
        prewitt_y[7] = -1.0;
        prewitt_y[8] = -1.0;
    
        // 卷积操作
        vec4 edgeX = vec4( 0.0 );
        vec4 edgeY = vec4( 0.0 );
        for ( int i = 0; i < 9; ++i )
        {
            edgeX += texColor[i] * prewitt_x[i];
            edgeY += texColor[i] * prewitt_y[i];
        }
    
        vec4 edgeColor = sqrt( ( edgeX * edgeX ) + ( edgeY * edgeY ) );
        float edgeIntensity = gray( edgeColor );
        const float threshold = 0.05;
    
        if ( edgeIntensity > threshold )
            gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
        else discard;
    }

           因为代码相对较长,我必须把来github在。

    有需要的同行和朋友,从能github有资格代替代码。

    地址:这里

  • 相关阅读:
    LeetCode "Median of Two Sorted Arrays"
    LeetCode "Distinct Subsequences"
    LeetCode "Permutation Sequence"

    LeetCode "Linked List Cycle II"
    LeetCode "Best Time to Buy and Sell Stock III"
    LeetCode "4Sum"
    LeetCode "3Sum closest"
    LeetCode "3Sum"
    LeetCode "Container With Most Water"
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5031713.html
Copyright © 2011-2022 走看看