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有资格代替代码。

地址:这里

最新文章

  1. Vmware无法获取快照信息 锁定文件失败
  2. sql 重复数据只保留一条
  3. ssh An internal error occured during &quot;Add Deployment&quot;
  4. 带你玩转JavaWeb开发之三 - CSS从基础到实战
  5. JAVA架构师要求
  6. freemarker 自定义标签
  7. .Net 乱序方法
  8. Careercup - Microsoft面试题 - 5943729928011776
  9. 通过示波器分析TypeB卡通讯数据
  10. Cocos2d-x 游戏植入广告(百度插屏)
  11. 老oj1965:polygon半平面交
  12. db2 update 异常
  13. iOS中 支付宝钱包详解/第三方支付 韩俊强的博客
  14. vue笔记-生命周期
  15. Schlumberger Petrel 2016.3 地震解释 油藏模拟
  16. Python数据结构之单链表
  17. CY7C68013 USB接口相机开发记录 - 第三天:固件修改
  18. 使用INTERSECT运算符
  19. java搭建web从0-1(第一步:创建web工程)
  20. SQL 中LTrim、RTrim与Trim的用法

热门文章

  1. Swift - 使用arc4random()、arc4random_uniform()取得随机数
  2. 3TB硬盘的容量已经超出了传统分区标准的支持
  3. gcc和g++的区别【转自中国源码网】
  4. 如何在Android Studio上使用Github
  5. 在Window和Linux下使用Zthread库
  6. Common Lisp学习笔记(0):从SLIME开始 | 优哉·幽斋
  7. 从O2O体验活动看华硕平板也“来电”新融合理念
  8. MySQL学习笔记之中的一个 MySQL入门
  9. OpenGL--第一个OpenGL程序
  10. zoj 2822 Sum of Different Primes (01背包)