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

之前写了两篇文章,介绍了我在边缘检測上面的研究。实际上。使用GPU对渲染图像进行边缘检測。前提是须要进行两遍渲染。前一遍渲染的结果作为后一遍结果的输入纹理。接着在第二遍渲染的时候,对二维图像做一些图像处理,终于得出带轮廓的描边渲染效果,接着和正常渲染混合在一起。就成为渲染的终于图像。但是,这种做法,是对二维图像做的图像处理,即使像上次对提取的深度进行图像处理,也无法准确地依据深度的突变来提取我们须要的边缘。所以我们须要新的方法来提取模型的边缘。

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

在这样的情况下,我在网上搜索到了

url=MdQtjaqp8bvHYEOM4K4VqLke2R_Uqgg3feCxNWFonYigyqOwcRQA7sR9LmyjxwiwEnTpA5a0GllnW_FAmHv3cK&wd=opengl%20%E6%8F%8F%E8%BE%B9&issp=1&f=3&ie=utf-8&tn=baiduhome_pg&oq=OpenGL&rsp=1&inputT=1055406">一篇文章。介绍了提取轮廓的方法:

1、顶点着色阶段,计算在view视角下的顶点到视点原点向量与在顶点位置向量的法向量。

2、对顶点到视点原点向量与法向量归一化,然后进行点积,表示夹角θ的cos值

3、假设cosθ>0,那么意味着θ<90°。能够代表这个顶点所在的面(当然也有可能是面面相交的棱上的点)朝向视点。表示正面,既然是正面,就显示原顶点位置;假设cosθ<0,那么意味着90°<θ<180°。能够代表这个面是背面。于是须要将顶点沿着法线偏移一定的距离,形成silhouette(轮廓)。

4、片断着色阶段,假设是正面的话,那么显示的是正常的片元颜色,否则显示的是黑色(或者是其他暗色)。

依据这种流程,我写了一个简单的着色器:

// Silhouette.vert
#version 100 // Qt 3D默认提供的參数
attribute vec3 vertexPosition;
attribute vec3 vertexNormal;
uniform mat4 modelView;
uniform mat3 modelViewNormal;
uniform mat4 modelNormalMatrix;
uniform mat4 mvp; // 自己提供的參数
uniform vec3 lightPosition;
varying float lightIntensity; float getLightIntensity( )
{
vec3 ecPos = vec3( modelView * vec4( vertexPosition, 1.0 ) );
vec3 normal = modelViewNormal * vertexNormal;
ecPos = normalize( ecPos );
normal = normalize( normal );
return dot( -ecPos, normal );
} void main( void )
{
const float bias = 0.2;
vec3 silhouettePosition = vertexPosition + normalize( vertexNormal ) * bias;
lightIntensity = getLightIntensity( );
if ( lightIntensity > 0.0 ) gl_Position = mvp * vec4( vertexPosition, 1.0 );
else gl_Position = mvp * vec4( silhouettePosition, 1.0 );
} // Silhouette.frag
#version 110 // 自己提供的參数
varying float lightIntensity; void main( void )
{
vec4 light = vec4( 0.9, 0.7, 0.5, 1.0 );
vec4 dark = vec4( 0.0, 0.0, 0.0, 1.0 );
gl_FragColor = lightIntensity > 0.0? light: dark;
}

执行的结果例如以下:

这里须要开启深度測试,測试公式是lessOrEqual。代码例如以下:

DepthTest { func: DepthTest.LessOrEqual }

看来基本轮廓已经显示出来了,接下来要结合前段时间制作的卡通渲染效果。来一个结合。终于制作的ToonSilhouette着色器例如以下:


// ToonSilhouette.vert
#version 100 // Qt 3D默认提供的參数
attribute vec3 vertexPosition;
attribute vec3 vertexNormal;
uniform mat4 modelView;
uniform mat3 modelViewNormal;
uniform mat4 modelNormalMatrix;
uniform mat4 mvp; // 自己提供的參数
uniform vec3 lightPosition;
varying float lightIntensity; float getLightIntensity( )
{
vec3 ecPos = vec3( modelView * vec4( vertexPosition, 1.0 ) );
vec3 normal = modelViewNormal * vertexNormal;
ecPos = normalize( ecPos );
normal = normalize( normal );
return dot( -ecPos, normal );
} void main( void )
{
const float bias = 0.1;
vec3 silhouettePosition = vertexPosition + normalize( vertexNormal ) * bias;
lightIntensity = getLightIntensity( );
if ( lightIntensity > 0.0 ) gl_Position = mvp * vec4( vertexPosition, 1.0 );
else gl_Position = mvp * vec4( silhouettePosition, 1.0 );
} // ToonSilhouette.frag
#version 110 // 自己提供的參数
uniform sampler2D texPalette;
varying float lightIntensity; void main( void )
{
vec4 light = vec4( 0.9, 0.7, 0.5, 1.0 );
vec4 dark = vec4( 0.0, 0.0, 0.0, 1.0 );
vec4 toon = texture2D( texPalette, vec2( lightIntensity, 1.0 ) );
gl_FragColor = lightIntensity > 0.0? toon: dark;
}

演示程序的截图例如以下:

这样看起来饱满多了。

因为程序较长。我将全部代码放在了github中。有须要的同行朋友们能够从这个地址上clone执行之。

Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader的更多相关文章

  1. 使用Qt 3D Studio 2.4显着提升性能(渲染速度提高了565%)

    发布于2019年6月18日星期二11评论Qt 3D Studio 2.4显着改善性能 发表于Biz Circuit&Dev Loop,设计,图形,性能,Qt 3D Studio 除了有效使用系 ...

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

    Qt 3D研究(九):尝试第二边缘检测方法 三维应用程序,通过FBO.将3D图像渲染成纹理,然后对渲染成的纹理进行图像处理,终于显示在屏幕上的.是风格化后的图案.上一次我使用了一种普通的图像处理方法: ...

  3. 从0开发3D引擎(十二):使用领域驱动设计,从最小3D程序中提炼引擎(第三部分)

    目录 上一篇博文 继续实现 实现"DirectorJsAPI.init" 实现"保存WebGL上下文"限界上下文 实现"初始化所有Shader&quo ...

  4. 【十天自制软渲染器】DAY 01:图形学学习建议与环境搭建

    推荐直接阅读博客原文,更新更及时,阅读体验更佳 「十天自制软渲染器」这个标题我承认标题党了.在对图形学一无所知的情况下想十天自制一个软渲染器,就好似一节课没上过却试图一个晚上看完<30 天精通 ...

  5. 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/ ...

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

    Qt 3D教程(三)实现对模型材质參数的控制 蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/47131841.欢迎同行前来探讨. ...

  7. 基于物理渲染的渲染器Tiberius计划

    既然决定实现一个光栅化软件渲染器,我又萌生了一个念头:实现一个基于物理渲染的渲染器.

  8. 微信小程序学习笔记二 列表渲染 + 条件渲染

    1. 列表渲染 1.1 wx:for 在组件上使用wx:for控制属性绑定一个数组, 即可使用数组中各项的数据重复渲染该组件 默认数组的当前项的下标变量名默认为 index, 数组当前项的变量名默认为 ...

  9. Qt 2D绘图之二:抗锯齿渲染和坐标系统

    一.抗锯齿渲染 1.1 逻辑绘图 图形基元的大小(宽度和高度)始终与其数学模型相对应,下图示意了忽略其渲染时使用的画笔的宽度的样子. 1.2 物理绘图(默认情况) 在默认的情况下,绘制会产生锯齿,并且 ...

随机推荐

  1. PCB MS SERVER 数据导出与导入操作步骤----使用第3方工具

    工作每天都与数据库打交道,经常会遇到一些需要将数据库中的数据导出来或将数据导入到数据库 而用微软数据库客户端自带的功能操作步骤好麻烦的,用过的大家都会有相同的感受吧. 微软客户端不好之处整理:这里吐槽 ...

  2. PCB 线路板人生

    由此开端,增加PCB人生分类栏,后续在此分享PCB 非工作方面所思所想,由于文笔不好,请指正.

  3. centos vi和vim用法

    所有的 Unix Like 系统都会内建 vi 文书编辑器,其他的文书编辑器则不一定会存在. 但是目前我们使用比较多的是 vim 编辑器. vim 具有程序编辑的能力,可以主动的以字体颜色辨别语法的正 ...

  4. CAS配置(3)之restful-api接入接口

    第一步,cas服务端对api接口支持 在cas-server-webapp下 pom.xml添加如下依赖 <dependency> <groupId>org.jasig.cas ...

  5. C# 多线程系列(四)

    Parallel类 Parallel类定义了for.foreach和invoke的静态方法.Parallel类使用多个任务,因此使用多个线程来完成这个作业. Parallel.For Parallel ...

  6. Leetcode0024--Swap Nodes in Pairs 链表配对交换

    [转载请注明]http://www.cnblogs.com/igoslly/p/8707274.html 来看一下题目: Given a linked list, swap every two adj ...

  7. android学习-第二讲(修改项目名称和图标,log,过滤器)

    一.在app/src/main/res下有 AndroidManifest.xml打开,打开后如下图1 二.日志工具log log.v()  log.d()  log.i()  log.w()  lo ...

  8. C# Socket通讯 本机多网卡,指定网卡通讯

    IPAddress ip = IPAddress.Parse("192.168.0.188"); IPAddress IPLocal = IPAddress.Parse(" ...

  9. python 生成测试报告并发送邮件

    前言: 使用unittest编写自动化测试脚本,执行脚本后可以很方便看到测试用例的执行情况. 但如果想向领导汇报工作,就需要提供更直观的测试报告. 思路: 使用unittest编写测试用例,HTMLT ...

  10. Python统计字符串中出现次数最多的人名

    人名最多数统计题目摘自https://python123.io 描述编程模板中给出了一个字符串,其中包含了含有重复的人名,请直接输出出现最多的人名.‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬ ...