Vertex Shader 支持的卡通描边渲染
Cell Style Rendering use vertex shader
潘李亮 2003-10-4
Stanly Lee 2003-10-4
Email : xheartblue@etang.com
Homepage gamehunter.3322.net/xpertsoft/
通常情况下,我们见到3D场景都是按照真实的光照模型来照明渲染的,虽然目前实时的光照模型还只是对真实世界的一种近似。但是这种模型已经有了良好的可接受的真实感。
在人们想法提高场景渲染结果的同时,其他的非真实感渲染技术也是非常有用的,比较常见的就是卡通风格的渲染,这种渲染结果类似于我们常见的卡通画。本文将介绍使用Vertex shader来实现一种卡通风格的渲染。
1. 什么是卡通风格的渲染
首先我们要弄清楚什么是卡通风格的渲染结果,即我们需要得到什么样的效果。考察下图的茶壶渲染结果,我们得出以下的结论:
图1,以卡通风格渲染的茶壶模型。
1、 要有比较明显边缘黑线,即明显的轮廓感觉。
2、 要有很急剧的明暗对比度,即颜色变化比较的快。
3、 考虑到视点变化的时候,我们也应该得到相同的效果。
2、解决方案。
对于上面提到的第3点需求,我们必须建立一个在视空间中的光照方向。这个光照的方向是不应该受到变换矩阵的影响的。同时这个光照方向应该和我们观察方向是一致的,只有这样才能得到如图一所示的明暗效果。
产生边缘轮廓线的方法有很多,最容易想到的就是绘制两遍场景,第一次按正常的光照模型来绘制,第二遍以线框的模式来绘制,同时将Z-Buffer的检测设置为相等的时候才通过。但是这样做的缺点是很明显的:首先你要绘制两遍场景,严重的影响了性能。其次是你在D3D里无法设置线的宽度,你只能得到比较单薄的轮廓。第二种方法是用观察方向(Camera的方向)去点乘转换后的三角形的法向量。点积的结果表示了一个三角形靠近边缘的程度,边缘必定是由一个正面朝向的三角形和一个背面朝向的三角形的公共边。如果一个三角形的法向量和Camera的方向的点积的绝对值越小则表示它离边缘越近,如果点积是负的话则表示它是背离了观察者。我们可以把靠近边缘的三角形渲染成黑色,这样就可以给物体制造一种很重的边缘效果。
图2,光线与三角形法线夹角对光照强度的影响,纵坐标为光照强度,横坐标为夹角
最后是如何创建急剧的明暗变化问题,正常的光源方向和法线夹角对光照强度的影响如图2。正常的光照为蓝色的线条所示,通常它是条余弦曲线。为了达到我们需要的效果,我们希望的曲线是如上图的绿色所示的。角度小于一定数值时候,曲线较平坦,表示我们看到的大部分区域有较亮的着色效果,在经过一段急剧的变换以后,在接近90度的地方又变的很平坦(图2中的红色圆圈内的曲线),这是主要因为我们要制造一个比较浓重的边缘线条效果。
3,实现方法
在通常的做法中,要把视空间的法向量映射成亮度的话有两种方法。一种是事先做好一个一维纹理,纹理地址从0-256之间的值的变化是按照图2的亮度曲线定义的。一个顶点的纹理坐标是根据它的法向量来决定的,这需要我们给D3D/OpenGL来指定一定的纹理坐标自动生成算法。第二种方法是使用Cube Map。Cube Map是用一个向量(在这里是顶点的法向量)来索引一个纹理的像素。这种方法需要我们生成一个特殊的Cube纹理,而且也需要特定的自动纹理坐标生成方法。
以上两种方法都是用纹理来照明整个模型的,都需要占用一个纹理级别(Texture Stage)。而且也都不太直观(相对来说,第一种方法稍微直观一点)。
由于观察者的朝向(Camera的朝向)是一定的,因此我们只要能把法向量变换到视空间里,同时能在计算光照的时候,构造一条像图2中的曲线就可以实现需要的卡通渲染效果了,也就是说只要我们能控制T&L过程就可以了。这在现在的3D API和图形卡中都是很容易实现的。Vertex Shader提供了对这方面的全面支持。
4、 光照曲线的构造方法
由于Vertex Shader是Per-Vertex的形式处理的,我们不应该建立一个很复杂的计算代码。要达到图2所示的曲线最简单的方法就是给计算好的法线和Camera方向的点积乘上一个倍数,然后再减去一个数值。具体的曲线关系如图3,图中粉红色的为正常的光照模型曲线,我们先将其放大到一定的倍数到绿色曲线,然后再向下平移到蓝色曲线位置,由于3D API会将大于1的截断到1,小于0的归整到0。最终我们得到的光照曲线如红色的曲线所示。这种方法在D3D的VS2.0的版本中只要多增加一条指令(mad)就可以实现。但是由于D3D支持创建亮度大于1的光照,因此这种方法的渲染结果带有明显的金属亮泽。
VS2.0中有一条slt指令,这条指令可以根据两个操作数的大小的不同来选择是将目的操作寄存器设置为1还是0。我们可以用这条指令来做出如图4一样的曲线来。
图3 图 4
5、 代码
本文不是一篇Vertex Shader的教程,所以我不会对如何使用以及什么是Vertex Shader花费过多的力气。本文的程序是用D3D实现的。我没有给顶点添加任何的数据。也就是D3D部分和普通的画Tearpot的程序没有任何的不同。因此我在这里只给出我的vertex shader的代码。
vs_2_0 // version instruction
dcl_position v0 // define position data in register v0
dcl_normal v4
def c15,1,1,1,0 //光的颜色
def c14,1.5,1.5,1.5,7 //一些在计算卡通效果时用到的常数
def c16,0,0,1,0 //定义眼睛的位置
def c17,0.5,2,0.3,0 //定义了图4中3条横线的位置
//大于c17.x的都放大到1,c17.y则负责把c1.x放大到1,小于c17.z的都缩小为0
m4x4 oPos, v0, c0 //将点通过变换矩阵变换到投影空间
m3x4 r0,v4,c0 //将法向量变换到投影空间里来
nrm r1,r0 //单位化法向量
dp3 r1,r1,-c16 //计算正常的光照模型,将camera方向与法向量做点积
//=============以下的代码形成图4的曲线===========
//形成卡通渲染的关键步骤
slt r1.w,r1.x,c17.x
slt r1.z,-r1.x,-c17.x
slt r1.y,-r1.x,-c17.z
mul r1.x,r1.x,r1.w
mad r1.x,r1.x,c17.y,r1.z //将大于c17.x都放大到1,并将0-c17.x的放大到0-1的范围
mul r1.x,r1.x,r1.y //将小于c17.z的都变成0
//==============形成图3所示的卡通光照效果==================
//下面的代码也可以形成卡通效果,但是看上去更加的浓重Metal效果
//mad r1,r1,c14.w,-c14
//====施加卡通光照效果========
mul oD0 ,r1.x,c15
使用 图4的曲线渲染结果
使用图3曲线的渲染结果
相关推荐
描边 Pass 中,在 vertex shader 中对模型沿顶点法线方向放大,fragment shader 设置输出颜色为描边颜色;第二遍正常绘制模型,除被放大的部分外,其余被覆盖,这样就有了描边的效果。 Shader 代码分析 在 Shader ...
在Unity中,你可以创建一个新的Shader,基于内置的Surface Shader或者Vertex Fragment Shader,然后在Shader代码中添加描边逻辑。关键在于检测每个像素是否位于模型的边缘,并根据结果调整颜色。 - 描边Shader通常...
首先,DX9 Shader分为两种类型:顶点着色器(Vertex Shader)和像素着色器(Pixel Shader)。顶点着色器处理模型的顶点数据,包括位置、法线、纹理坐标等,执行变换和光照计算,将3D模型转换为2D图像。像素着色器则...
在IT领域,游戏开发是其中一个重要的分支,而Irrlicht是一个流行且开源的3D游戏引擎,被广泛...在实际应用中,可以根据项目需求调整卡通渲染的效果,比如增加阴影、描边或其他特效,以创造出更加丰富多彩的视觉体验。
理解基础的CG语言和Unity的Shader语言语法是必不可少的,包括结构体(structs)、输入(inputs)、输出(outputs)、顶点函数(vertex function)和片段函数(fragment function)等。 文件名"超牛逼~外发光shader...
首先,你需要编写GLSL代码,这是Shader语言,包括顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)。这两个着色器定义了如何处理输入的顶点数据以及如何为每个像素生成颜色。然后,将这些Shader代码导入...
Unity是一款广泛应用于游戏开发、虚拟现实(VR)和增强现实(AR)的三维交互引擎,其强大的图形渲染能力很大程度上得益于Shader技术。Shader是编写在图形处理单元(GPU)上运行的程序,用于控制物体表面的光照、颜色、纹理...
例如,可能包含用于高级光照模型(如Subsurface Scattering次表面散射,Specular AA镜面抗锯齿)的Shader,或者是特定渲染模式(如Outline描边,Decals贴花)的实现。研究这些Shader可以帮助开发者实现更复杂的游戏...
Unity Shader 主要分为两种:Vertex Shader 和 Fragment Shader。 Vertex Shader 负责处理顶点数据,而 Fragment Shader 负责处理像素数据。 知识点二:素描效果的实现原理 素描效果是通过对物体进行描边和漫反射...
Cocos2d-x 3.17.2版本支持C++编程语言,提供了丰富的API接口来创建和管理Shader。在给定的文件名列表中,我们看到的是几种不同效果的基础Shader实现,包括色彩转换(hue)、描边(stroke)、灰度(gray)、模糊...
首先,我们看到Shader代码的开头定义了一个名为"Outlined/Silhouetted Diffuse"的着色器,这表明它将用于处理物体的表面颜色和描边。着色器的属性包括: 1. `_Color`:主颜色,是一个颜色属性,默认值为白色,用于...
描边宽度节点将向着色器添加描边效果,通过具有反面法线的偏移网格进行渲染。 ### 描边颜色(Outline Color) 描边颜色节点控制描边的颜色。 ### 顶点偏移(Vertex Offset) 顶点偏移节点可用于对着色器进行动画...
在三维图形渲染中,物体描边效果是一种常见且...完整实现代码可以在提供的链接中查看,这只是一个基础示例,实际应用中可能需要根据项目需求进行调整,例如增加对不同颜色物体描边的支持,或者调整描边的样式和效果。
Unity支持两种主要类型的Shader:Surface Shaders和Vertex/Fragment Shaders。在这个案例中,我们可能会使用Surface Shader,因为它们更适合处理复杂的表面效果,且编写起来相对简单。 2. 物体轮廓渲染: 要显示...
在这个项目中,我们关注的是顶点着色器(Vertex Shader)和像素着色器(Pixel Shader),这两个着色器工作在一起,为每个像素生成最终的卡通外观。 1. **顶点着色器**:顶点着色器处理模型的几何数据,包括位置、...
- **编写HLSL代码**:在RenderMonkey中编写Vertex Shader和Pixel Shader代码,利用内置函数和结构体来处理顶点和像素数据。 - **调试与优化**:使用RenderMonkey提供的调试工具来检查Shader的执行结果,通过查看实时...
着色器分为两种主要类型:顶点着色器(Vertex Shader)和片段着色器(Fragment Shader)。顶点着色器处理图形的顶点数据,如位置、颜色和法线,而片段着色器则处理每个像素的颜色值。 在这个项目“android-gpuimage...
此外,还有Unlit着色器,用于不考虑光照的简单渲染,以及各种特殊效果着色器,如Outline(描边)和Toon(卡通渲染)等。 2. **ShaderLab语法**:ShaderLab 的语法简单明了,包括Properties(属性)、SubShader(子...
- **Pass**:着色器的绘制阶段,每个Pass执行一次渲染操作,可以用于不同的渲染目的,如主渲染、描边等。 3. **关键指令**: - `CGPROGRAM` 和 `ENDCG`:包围着Cg/HLSL代码段,这些是GPU可执行的代码。 - `...
理解ShaderLab的基础语法,如表面着色器(Surface Shaders)、顶点着色器(Vertex Shaders)和片段着色器(Fragment Shaders)。 2. **2D渲染**:在Unity中,2D渲染主要依赖于Sprite Renderer组件。通过调整其属性...