Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader
来源:互联网 发布:js div滚动条触发事件 编辑:程序博客网 时间:2024/03/28 22:19
Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader
之前写了两篇文章,介绍了我在边缘检测上面的研究,实际上,使用GPU对渲染图像进行边缘检测,前提是需要进行两遍渲染,前一遍渲染的结果作为后一遍结果的输入纹理,接着在第二遍渲染的时候,对二维图像做一些图像处理,最终得出带轮廓的描边渲染效果,接着和正常渲染混合在一起,就成为渲染的最终图像。可是,这样的做法,是对二维图像做的图像处理,即使像上次对提取的深度进行图像处理,也无法准确地根据深度的突变来提取我们需要的边缘。所以我们需要新的方法来提取模型的边缘。
蒋彩阳原创文章,首发地址:http://blog.csdn.net/gamesdev/article/details/44455901。欢迎同行前来探讨。
在这种情况下,我在网上搜索到了一篇文章,介绍了提取轮廓的方法:
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
- Qt 3D的研究(四):指定渲染的材质以及效果
- Qt 3D的研究(七):渲染至纹理
- 3D引擎:Horde3D:Shader类里的 结构体,以及渲染一个 Logo的简单流程(三)
- Shader和3D图形渲染管线(Render Pipeline)
- OPenGL/3D渲染/shader
- Qt 3D的研究(五):Gooch Shader
- Qt 3D的研究(六):Toon Shader
- 对3D渲染管线(渲染流水线)的理解
- Unity Shader 学习笔记(27)渲染轮廓线(描边)方法、卡通风格渲染、素描风格渲染
- 图像渲染(Shader)
- 图像渲染(Shader)
- android 图像渲染(Shader)
- 【Metal API 教程:第二讲】编写Metal Shader并渲染3D模型(上)
- Qt新渲染底层Scene Graph研究(一)
- Qt新渲染底层Scene Graph研究(二)
- Qt新渲染底层Scene Graph研究(三)
- Vertex Shader 支持的卡通描边渲染
- 惨痛教训 beego路由失败
- YTUOJ-判断字符串是否为回文
- phonegap archive 报错 Cordova/CDVViewController.h' file not found
- php文件上传类,支持产生文件缩略图
- Big Endian 和 Little Endian
- Qt 3D的研究(十):描边渲染(轮廓渲染)以及Silhouette Shader
- 【笔记3】获取csi文件,并用MATLAB处理
- 解决VS2008无法打开预编译头Debug\XXX.pch,请重启VS的提示
- 黑马程序员——Object-C基础(五)面向对象的特性:封装
- 10-使用windows7自带的刻录软件刻录光盘
- hdu 1253 胜利大逃亡
- 参照网上修改后的插入算法
- 安卓横竖屏切换问题总结
- Dynamics CRM Microsoft SQL Server 指定的数据库具有更高的版本