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有资格代替代码。
地址:这里
Qt 3D研究(九):尝试第二边缘检测方法的更多相关文章
- Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader
Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader 之前写了两篇文章,介绍了我在边缘检測上面的研究.实际上.使用GPU对渲染图像进行边缘检測.前提是须要进行两遍渲染.前 ...
- Qt中中文字符 一劳永逸的解决方法
QT中中文字符问题,有没有一劳永逸的解决方法? 目前遇到有以下问题 1.字符串中有中文时,编译提示"常量中含有换行符" 2.在控制台窗口输出中文时无法正常显示,中文全部显示为? 目 ...
- 使用Qt 3D Studio 2.4显着提升性能(渲染速度提高了565%)
发布于2019年6月18日星期二11评论Qt 3D Studio 2.4显着改善性能 发表于Biz Circuit&Dev Loop,设计,图形,性能,Qt 3D Studio 除了有效使用系 ...
- Unity 3D游戏开发学习路线(方法篇)
Unity 3D本来是由德国的一些苹果粉丝开发的一款游戏引擎,一直只能用于Mac平台,所以一直不被业外人士所知晓.但是后来也推出了2.5版,同时发布了PC版本,并将其发布方向拓展到手持移动设备.Uni ...
- Qt 3D Studio 1.0 Resleased
Qt 这家伙又整出一个新东西了,Qt 3D Studio 1.0 新闻链接:https://blog.qt.io/blog/2017/11/30/qt-3d-studio-1-0-released/ ...
- 修改Chem 3D模型的化学键属性的方法有哪些
很多的用户在绘制化学图形过程中发现很多的图形都是立体结构的,这个时候就需要用Chem3D,它是ChemOffice的核心组件之一,在绘制立体模型和计算化学数据方面具有不可替代的作用.虽然ChemDra ...
- Qt 3D教程(三)实现对模型材质參数的控制
Qt 3D教程(三)实现对模型材质參数的控制 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/47131841.欢迎同行前来探讨. ...
- monkey工具使用中遇到的问题之二:尝试了各种方法通过adb都无法找到设备
测试环境: 1.用的是adt-bundle-windows-x86_64-20140702里面的adb 2.用的是手机模拟器(夜神) 问题描述: 已搭建好adb的环境,输入adb,可以看到以下相关信息 ...
- ios更新UI时请尝试使用performSelectorOnMainThread方法
最近开发项目时发现联网获取到数据后,使用通知方式让列表刷新会存在死机的问题. 经过上网查找很多文章,都建议使用异步更新的方式,可是依然崩溃. 最后尝试使用performSelectorOnMainTh ...
随机推荐
- 改动已有gpg密钥的用户标识及凝视
/********************************************************************* * Author : Samson * Date ...
- ANDROID L——Material Design综合应用(Demo)
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! Material Design: Material Design是Google推出的一个全 ...
- Java IO学习笔记:概念与原理
Java IO学习笔记:概念与原理 一.概念 Java中对文件的操作是以流的方式进行的.流是Java内存中的一组有序数据序列.Java将数据从源(文件.内存.键盘.网络)读入到内存 中,形成了 ...
- Windows移动开发(四)——闭关修炼
非常久不写博客了,不是由于不想写,仅仅是近期公司任务比較多,最终十一有时间出来冒泡了. 今天继续介绍移动开发中的重中之重--内存管理. C#代码是托管代码,C# 程序猿非常少像C/CPP程序猿那样为程 ...
- JavaBean在DAO设计模式简介
一.信息系统开发框架 客户层-------显示层-------业务层---------数据层---------数据库 1.客户层:客户层是client,简单的来说就是浏览器. 2.显示层:JSP/Se ...
- 分类器是如何做检测的?——CascadeClassifier中的detectMultiScale函数解读
原地址:http://blog.csdn.net/delltdk/article/details/9186875 在进入detectMultiScal函数之前,首先需要对CascadeClassifi ...
- jQuery中常用的函数方法
jQuery中常用的函数方法总结 Ajax处理 load(url,[data],[callback]) url (String) : 待装入 HTML 网页网址. data (Map) : (可选) ...
- js封装好的模仿qq消息弹窗代码
在我们的日常开发中,或者生活中.常常须要用到弹出窗.这里我们就用js模拟一下qq消息一样的弹出窗. 直接贴代码: <!DOCTYPE html PUBLIC "-//W3C//DTD ...
- Codeforces 61E Enemy is weak 乞讨i<j<k && a[i]>a[j]>a[k] 对数的 树阵
主题链接:点击打开链接 意大利正在寻求称号 i<j<k && a[i]>a[j]>a[k] 的对数 假设仅仅有2元组那就是求逆序数的做法 三元组的话就用一个树状 ...
- 服务器编程入门(3)TCP协议详解
问题聚焦: 本节从如下四个方面讨论TCP协议: TCP头部信息:指定通信的源端端口号.目的端端口号.管理TCP连接,控制两个方向的数据流 TCP状态转移过程:TCP连接的任意一 ...