Qt 3D的研究(八):边缘检测

Qt 3D的研究(八):边缘检测

上一篇文章讲到了如何使用渲染至纹理技术将我们第一遍渲染保存至纹理以便做一些操作。还是上一次的例子,我简要地分析一下如何进行边缘检测。

蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44194475。欢迎同行前来探讨。

还是上次的图片:

我们这里做了两遍渲染。第一遍渲染使用卡通渲染的方法执行,如下:

有关第一遍卡通渲染的着色器代码,可以参考我以前写的一篇文章。接下来,我们通过渲染至纹理技术,将帧缓存中的colorattachment以及depth attachment分别输出至两个不同的纹理中。这里需要注意,即使我们选定的窗口不是2n的大小,我们选择作为renderattachment的纹理必须是2n的大小。输出至纹理很重要,因为在第二遍渲染(2ndrender
pass)中,我们需要将纹理作为采样器传递给GLSL,并且在片断着色器中进行采样。下面是第二遍渲染的GLSL代码:

// 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 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 sobel_x[9];
    sobel_x[0] = -1.0;
    sobel_x[1] = 0.0;
    sobel_x[2] = 1.0;
    sobel_x[3] = -2.0;
    sobel_x[4] = 0.0;
    sobel_x[5] = 2.0;
    sobel_x[6] = -1.0;
    sobel_x[7] = 0.0;
    sobel_x[8] = 1.0;

    float sobel_y[9];
    sobel_y[0] = 1.0;
    sobel_y[1] = 2.0;
    sobel_y[2] = 1.0;
    sobel_y[3] = 0.0;
    sobel_y[4] = 0.0;
    sobel_y[5] = 0.0;
    sobel_y[6] = -1.0;
    sobel_y[7] = -2.0;
    sobel_y[8] = -1.0;

    // 卷积操作
    vec4 edgeX = vec4( 0.0 );
    vec4 edgeY = vec4( 0.0 );
    for ( int i = 0; i < 9; ++i )
    {
        edgeX += texColor[i] * sobel_x[i];
        edgeY += texColor[i] * sobel_y[i];
    }

    vec4 edgeColor = sqrt( ( edgeX * edgeX ) + ( edgeY * edgeY ) );
    float edgeIntensity = gray( edgeColor );
    const float threshold = 0.5;
    if ( edgeIntensity > threshold )
        gl_FragColor = vec4( 0.0, 0.0, 0.0, 1.0 );
    else discard;
}

colorAttachTex作为纹理的采样器,在此基础上,我们对纹理的每一个像素周围的9个像素点进行采样。这里我们采取了索贝尔(sobel)算子作为卷积核,除了索贝尔算子,还有拉普拉斯(laplace)算子以及普瑞维特(prewitt)算子进行选择。通过9个采样点和索贝尔算子进行卷积操作,就可以得到边缘。卷积操作的公式如下:

第二遍渲染仅保存了边缘,再加上用普通前向渲染渲染出来的图像,就可以得到带边缘的最终图像了。目前图像的显示还不完美,还出现了一些噪点,这可能需要修改阈值(threshold)进行调整来达到效果。

时间: 2024-10-02 10:25:30

Qt 3D的研究(八):边缘检测的相关文章

Qt 3D的研究(九):尝试另外一种边缘检测方法

Qt 3D的研究(九):尝试另外一种边缘检测方法 三维应用程序,通过FBO,将3D图像渲染成纹理,然后对渲染成的纹理进行图像处理,最终显示在屏幕上的,是风格化后的图案.上一次我使用了一种普通的图像处理方法:索贝尔边缘检测法,与我们的卡通渲染结合起来,实现了这样的效果,接着,我将采用另外一种边缘检测方法--普雷维特(Prewitt)边缘检测方法来重新渲染图案. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44405219.欢

Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader

Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader 之前写了两篇文章,介绍了我在边缘检测上面的研究,实际上,使用GPU对渲染图像进行边缘检测,前提是需要进行两遍渲染,前一遍渲染的结果作为后一遍结果的输入纹理,接着在第二遍渲染的时候,对二维图像做一些图像处理,最终得出带轮廓的描边渲染效果,接着和正常渲染混合在一起,就成为渲染的最终图像.可是,这样的做法,是对二维图像做的图像处理,即使像上次对提取的深度进行图像处理,也无法准确地根据深度的突变来提取我们需要的边缘.所以

Qt 3D的研究(五):Gooch Shader

Qt 3D的研究(五):Gooch Shader Qt 3D的一个很大的优势就是采用数据驱动的方式,将C++和GLSL使用QML来表示,动态语言的优势尽显.在上一次的研究中,我实现了一个非常简单的着色器,接下来,我们可以在此基础上,通过设定着色器的数据,制作出更加绚丽的着色效果.作为开始,我们先从几个非真实渲染(Non-Photorealistic Rendering,NPR)开始吧. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/deta

Qt 3D的研究(七):渲染至纹理

Qt 3D的研究(七):渲染至纹理 最近几天都没有怎么研究Qt 3D了,但是随着Qt5.5发布的日子一天天的靠近,我也不能懈怠,希望利用Qt 3D,将能够实现的功能进行实现,并且对Qt3D获取一个新的认识.两天多没有研究了,现在信心却是满满的! 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44156633.欢迎同行前来探讨. Qt 3D还是在发展的过程中,也没有什么文档,所以有什么问题的话,只能去问库的作者了.我就在IRC

Qt 3D的研究(六):Toon Shader

Qt 3D的研究(六):Toon Shader 在上次的实验中,我们实现了Gooch Shader,并给出了通过调色板进行个性化的Gooch Shader设置.Toon Shader又称Cell Shader,是以离散的颜色来表示光照的强弱.很多动画片的渲染方式都是使用Toon Shader的.下面这样图就可以使用Toon Shader实现. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44084021.欢迎同行前来探讨.

Qt 3D的研究(二)

上一篇文章给大家看了很多Qt 3D的例子,如果大家有Qt 3D的源代码,就会发现,开发这些例子,花费的代码还真不少.这就是不一样的地方,Qt 3D毕竟和三维图形打交道,多了一个维度,问题的难度变得更大了. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/43801957.欢迎同行前来探讨. 研究了多日的Qt 3D,我了解到为了适应跨平台.不同的着色器编译器标准.多重渲染目标,Qt 3D提出了很多的方案,创新了许多的概念,这多多

Qt 3D的研究(一)

Qt3D的研究(一) Qt 3D是有可能即将在Qt 5.5中正式启用的模块之一.它建立的目标是能够让开发者快速地创建3D场景,通过各式各样的渲染技术来达到3D交互的场景.Qt3D除了和Qt一样跨平台之外,还能够选择OpenGL的具体实现,定制GLSL,从而能够根据不同性能的机器,来调整渲染效果. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/43800383.欢迎同行前来探讨. Qt 3D在Qt 5.2的时候就传言即将登场了

Qt 3D研究(三):显示3D模型

Qt 3D研究(三):显示3D模型 上一篇文章介绍了如何使用最少的代码创建一个Qt 3D的应用.和大家最初接触的glut一样,对于3D应用来说,需要做的准备工作还真不少,不过呢,Qt 3D把一些窗口相关的琐碎事情解决了,剩下的,该由我们完成重要的渲染部分了,可以说,带来了某种程度的方便. 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/43964499.欢迎同行前来探讨. 我们接下来要使用Qt 3D将一个模型显示出来.Qt 3

Qt 3D教程(三)实现对模型材质参数的控制

Qt 3D教程(三)实现对模型材质参数的控制 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/47131841.欢迎同行前来探讨. 上一篇教程介绍的是显示一个三维模型的基本步骤,接下来我们需要实现的是添加材质,并且希望我们通过按钮来控制材质的参数.这样的效果看起来很像一个3D模型材质编辑器的样子.那我们来尝试一下吧. 首先我们对Settings这个类进行修改,给它增添一些属性,比如说环境光.漫反射.镜面反射以及反射系数.通过Q