写在前面

本系列其他文章:

好久没写博客了,一定是因为课程作业比较多,一定不是因为我懒,恩恩。

三个月以前,在一篇讲卡通风格的Shader的最后,我们说到在Surface Shader中实现描边效果的弊端,也就是只对表面平缓的模型有效。这是因为我们是依赖法线和视角的点乘结果来进行描边判断的,因此,对于那些平整的表面,它们的法线通常是一个常量或者会发生突变(例如立方体的每个面),这样就会导致最后的效果并非如我们所愿。如下图所示:

aaarticlea/png;base64,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" alt="" style="border: none; max-width: 100%;" />

因此,我们有一个更好的方法来实现描边效果,也就是通过两个pass进行渲染——首先渲染对象的背面,用黑色略微向外扩展一点,就是我们的描边效果;然后正常渲染正面即可。而我们应该知道,surface shader是不可以使用pass的。

在这篇里,我们就会学习如何使用Vertex & Fragment Shader来实现上述的过程。很显然,这样的一个过程包含了两个步骤——描边和正常的渲染。

最后的效果如下:

实现描边

上一篇里,我们使用了边缘高光来实现描边。而这篇里,我们将使用一个单独的pass来得到一个更好的效果。这里说的“更好”指的是以下几个方面:

  • 首先是对平整表面的适应性,如上面正方体的例子,这种方法仍可以得到期望的效果;
  • 而且这种方法可以不破坏正面模型的逼真度,也就是说正面模型可以完全不受影响。与之产生对比的是上一篇中的方法,使用边缘光照来实现的描边效果会影响到正面模型的表面,即正面模型也会有强烈的描边效果,而这往往不是我们所期望的。
因此,这个pass的第一个步骤就是剔除正面部分:
            Cull Front
Lighting Off

我们先来看frag函数,因此它的工作非常简单!就是输出黑色啦~当然如果你的描边不想要黑色可以在这里改写。

            float4 frag(v2f i) : COLOR
{
return float4(0, 0, 0, 1);
}

然后,我们继续计算vert函数部分。我们将会沿着顶点的法线方法向外扩张该点来模拟描边。因此,我们需要在下面的结构体中声明position和normal属性:

            struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
}; struct v2f
{
float4 pos : POSITION;
};

接下来,我们定义一个范围在0到1之间的_Outline的变量来控制描边的宽度。最后,vert函数如下:

                        float _Outline;

			v2f vert (a2v v)
{
v2f o;
o.pos = mul( UNITY_MATRIX_MVP, v.vertex + (float4(v.normal,0) * _Outline));
return o;
}

它的含义很好理解:把原先的顶点位置v.vertex沿着v.normal的方向扩展_Outline倍后,再转换到投影平面上输出最后的屏幕位置信息。

效果如下:
为了暴露问题,我把描边的宽度调的比较高。那么,问题来了。大家可以看出来哪里不太对吧?没错,就是眼睛和嘴巴的地方。为什么会有哪些很大的黑色色块呢?这是因为眼睛和嘴巴是独立于身体之外的两个网格,它们各自使用了一个新的材质,而它们的深度关系是眼睛和嘴巴在身体的后面(被身体的皮肤包裹嘛),因此在渲染的时候身体的渲染输出像素会覆盖眼睛和嘴巴的部分,也包括身体的描边部分,也就是说身体的黑色描边会覆盖眼睛和嘴巴的正常渲染,而这不是我们所希望的。一种暴力的解决方法就是直接关闭该pass的深度信息。即:
    		Cull Front
Lighting Off
ZWrite Off

这样一来,这个pass的结果是不写入深度缓存中的,而后面只要有其他材质要渲染该点的像素就会覆盖它。这样的效果如下:

那么,问题又来了。眼睛和嘴巴部分虽然对了,但小怪物的先后关系又乱了,即后面小怪物的身体挡住了前面小怪物的描边。而要解决这个问题,就要写入深度缓存。死循环了有木有!
其实,这说明我们生成描边的方法需要改进。我们回想为什么会出现眼睛和嘴巴那样的错误,是因为我们把描边的宽度调的太大了。我们之所以会这么做(当然这里我是故意的。。。),是因为有时候一些相邻顶点的法线指向非常不同,而为了得到我们想要的感性宽度,我们不得不调整的很大。而上述过程的实质其实就是把背光面的模型放大了而已,我们可以理解成它实际相当于一个新的黑色模型。这样放大的太过分了会发生什么呢?就是穿透和遮挡了。
而正确的方法应该是,把顶点当成轮廓处理而不是一个真正的模型。也就是说,当我们观察背面的某一个顶点时,要把它的Z方向的值扁平化,那么描边的结果就会主要受X和Y方向的影响。因此,

扁平化背面

首先,我们要在视角坐标系中处理描边。因为描边正是基于我们观察的角度而定的。因此,我们要把需要的变量都转换到视角坐标系下处理。这里面涉及两个变量——顶点的位置和顶点的法线。
顶点很好处理,只要使用UNITY_MATRIX_MV即可。法线的转换麻烦一点,这是因为法线并不是真正定义在模型坐标系中的,而是和它是正交的,我们需要使用ModelView转换矩阵的转置矩阵来把法线转换到视角坐标系中。原因可以看这里这里
因此,我们的工作包含下面几个步骤:
  • 把顶点位置转换到视角坐标系;
  • 把法线转换到视角坐标系;
  • 把转换后的法线的z值扁平化,即使其是一个较小的定值,这样所有的背面其实都在一个平面上;
  • 按描边的宽度放缩法线,并添加到转换后顶点的位置上,得到新的视角坐标系中的位置;
  • 把新的位置转换到投影坐标系中。
代码如下:
            v2f vert (a2v v)
{
v2f o; float4 pos = mul( UNITY_MATRIX_MV, v.vertex);
float3 normal = mul( (float3x3)UNITY_MATRIX_IT_MV, v.normal);
normal.z = -0.4;
pos = pos + float4(normalize(normal),0) * _Outline;
o.pos = mul(UNITY_MATRIX_P, pos); return o;
}

卡通化

后面这一部分没什么好解释的,和上一篇的方法一致,同样使用了简化颜色和渐变纹理来模拟卡通效果。

弊端

上一篇里的方法比,这里的方法解决了之前的两个弊端:一个是轮廓宽度无法精确保证,一个是对于法线突变的模型的不适应性。但它也有自己的弊端。最明显的就是,它无法和模型内部的褶皱添加轮廓。例如上面的小怪兽,只有它最外层的边界才有轮廓线,但其内部的肥肉褶皱则无法体现。而这种问题的解决方法,可以依靠第三种更高级的Shader来实现。具体请参见卡通风格的Shader(三)。

代码

我知道大家最想要的还是代码,上面很多人直接略过。Sigh~
还是把完整的代码给出。代码有两种,一种使用了法线纹理,一种没有使用法线纹理。每种都包含了三个pass:第一个pass处理背面进行描边,第二个pass处理正面的forwardbase,第三个pass处理正面的forwardadd。
在Vertex & Fragment中处理法线和光照,简直是噩梦啊!VF虐我千百遍,我却待她如初恋,哎。后面会写一篇这方面的文章,如果有时间的话。。。
首先是没有使用法线纹理的代码:
Shader "MyToon/Toon-Fragment" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_Ramp ("Ramp Texture", 2D) = "white" {}
_Tooniness ("Tooniness", Range(0.1,20)) = 4
_Outline ("Outline", Range(0,1)) = 0.1
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 Pass {
Tags { "LightMode"="ForwardBase" } Cull Front
Lighting Off
ZWrite On CGPROGRAM #pragma vertex vert
#pragma fragment frag #pragma multi_compile_fwdbase #include "UnityCG.cginc" float _Outline; struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
}; struct v2f
{
float4 pos : POSITION;
}; v2f vert (a2v v)
{
v2f o; float4 pos = mul( UNITY_MATRIX_MV, v.vertex);
float3 normal = mul( (float3x3)UNITY_MATRIX_IT_MV, v.normal);
normal.z = -0.5;
pos = pos + float4(normalize(normal),0) * _Outline;
o.pos = mul(UNITY_MATRIX_P, pos); return o;
} float4 frag(v2f i) : COLOR
{
return float4(0, 0, 0, 1);
} ENDCG
} Pass {
Tags { "LightMode"="ForwardBase" } Cull Back
Lighting On CGPROGRAM #pragma vertex vert
#pragma fragment frag #pragma multi_compile_fwdbase #include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "UnityShaderVariables.cginc" sampler2D _MainTex;
sampler2D _Ramp; float4 _MainTex_ST; float _Tooniness; struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 tangent : TANGENT;
}; struct v2f
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
LIGHTING_COORDS(2,3)
}; v2f vert (a2v v)
{
v2f o; //Transform the vertex to projection space
o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
o.normal = mul((float3x3)_Object2World, SCALED_NORMAL);
//Get the UV coordinates
o.uv = TRANSFORM_TEX (v.texcoord, _MainTex); // pass lighting information to pixel shader
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
} float4 frag(v2f i) : COLOR
{
//Get the color of the pixel from the texture
float4 c = tex2D (_MainTex, i.uv);
//Merge the colours
c.rgb = (floor(c.rgb*_Tooniness)/_Tooniness); //Based on the ambient light
float3 lightColor = UNITY_LIGHTMODEL_AMBIENT.xyz; //Work out this distance of the light
float atten = LIGHT_ATTENUATION(i);
//Angle to the light
float diff = dot (normalize(i.normal), normalize(_WorldSpaceLightPos0.xyz));
diff = diff * 0.5 + 0.5;
//Perform our toon light mapping
diff = tex2D(_Ramp, float2(diff, 0.5));
//Update the colour
lightColor += _LightColor0.rgb * (diff * atten);
//Product the final color
c.rgb = lightColor * c.rgb * 2;
return c; } ENDCG
}
Pass {
Tags { "LightMode"="ForwardAdd" } Cull Back
Lighting On
Blend One One CGPROGRAM #pragma vertex vert
#pragma fragment frag #pragma multi_compile_fwdadd #include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "UnityShaderVariables.cginc" sampler2D _MainTex;
sampler2D _Ramp; float4 _MainTex_ST; float _Tooniness; struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 tangent : TANGENT;
}; struct v2f
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float3 normal : TEXCOORD1;
half3 lightDir : TEXCOORD2;
LIGHTING_COORDS(3,4)
}; v2f vert (a2v v)
{
v2f o; //Transform the vertex to projection space
o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
o.normal = mul((float3x3)_Object2World, SCALED_NORMAL);
o.lightDir = WorldSpaceLightDir( v.vertex );
//Get the UV coordinates
o.uv = TRANSFORM_TEX (v.texcoord, _MainTex); // pass lighting information to pixel shader
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
} float4 frag(v2f i) : COLOR
{
//Get the color of the pixel from the texture
float4 c = tex2D (_MainTex, i.uv);
//Merge the colours
c.rgb = (floor(c.rgb*_Tooniness)/_Tooniness); //Based on the ambient light
float3 lightColor = float3(0); //Work out this distance of the light
float atten = LIGHT_ATTENUATION(i);
//Angle to the light
float diff = dot (normalize(i.normal), normalize(i.lightDir));
diff = diff * 0.5 + 0.5;
//Perform our toon light mapping
diff = tex2D(_Ramp, float2(diff, 0.5));
//Update the colour
lightColor += _LightColor0.rgb * (diff * atten);
//Product the final color
c.rgb = lightColor * c.rgb * 2;
return c;
} ENDCG
}
}
FallBack "Diffuse"
}

然后是使用了法线纹理的Shader:

Shader "MyToon/Toon-Fragment_Normal" {
Properties {
_MainTex ("Base (RGB)", 2D) = "white" {}
_Bump ("Bump", 2D) = "bump" {}
_Ramp ("Ramp Texture", 2D) = "white" {}
_Tooniness ("Tooniness", Range(0.1,20)) = 4
_Outline ("Outline", Range(0,1)) = 0.1
}
SubShader {
Tags { "RenderType"="Opaque" }
LOD 200 Pass {
Tags { "LightMode"="ForwardBase" } Cull Front
Lighting Off
ZWrite On CGPROGRAM #pragma vertex vert
#pragma fragment frag #pragma multi_compile_fwdbase #include "UnityCG.cginc" float _Outline; struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
}; struct v2f
{
float4 pos : POSITION;
}; v2f vert (a2v v)
{
v2f o; float4 pos = mul( UNITY_MATRIX_MV, v.vertex);
float3 normal = mul( (float3x3)UNITY_MATRIX_IT_MV, v.normal);
normal.z = -0.5;
pos = pos + float4(normalize(normal),0) * _Outline;
o.pos = mul(UNITY_MATRIX_P, pos); return o;
} float4 frag(v2f i) : COLOR
{
return float4(0, 0, 0, 1);
} ENDCG
} Pass {
Tags { "LightMode"="ForwardBase" } Cull Back
Lighting On CGPROGRAM #pragma vertex vert
#pragma fragment frag #pragma multi_compile_fwdbase #include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "UnityShaderVariables.cginc" sampler2D _MainTex;
sampler2D _Bump;
sampler2D _Ramp; float4 _MainTex_ST;
float4 _Bump_ST; float _Tooniness; struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 tangent : TANGENT;
}; struct v2f
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float2 uv2 : TEXCOORD1;
float3 lightDirection : TEXCOORD2;
LIGHTING_COORDS(3,4)
}; v2f vert (a2v v)
{
v2f o;
//Create a rotation matrix for tangent space
TANGENT_SPACE_ROTATION;
//Store the light's direction in tangent space
o.lightDirection = mul(rotation, ObjSpaceLightDir(v.vertex));
//Transform the vertex to projection space
o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
//Get the UV coordinates
o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
o.uv2 = TRANSFORM_TEX (v.texcoord, _Bump); // pass lighting information to pixel shader
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
} float4 frag(v2f i) : COLOR
{
//Get the color of the pixel from the texture
float4 c = tex2D (_MainTex, i.uv);
//Merge the colours
c.rgb = (floor(c.rgb*_Tooniness)/_Tooniness); //Get the normal from the bump map
float3 n = UnpackNormal(tex2D (_Bump, i.uv2)); //Based on the ambient light
float3 lightColor = UNITY_LIGHTMODEL_AMBIENT.xyz; //Work out this distance of the light
float atten = LIGHT_ATTENUATION(i);
//Angle to the light
float diff = saturate (dot (n, normalize(i.lightDirection)));
//Perform our toon light mapping
diff = tex2D(_Ramp, float2(diff, 0.5));
//Update the colour
lightColor += _LightColor0.rgb * (diff * atten);
//Product the final color
c.rgb = lightColor * c.rgb * 2;
return c; } ENDCG
}
Pass {
Tags { "LightMode"="ForwardAdd" } Cull Back
Lighting On
Blend One One CGPROGRAM #pragma vertex vert
#pragma fragment frag #pragma multi_compile_fwdadd #include "UnityCG.cginc"
#include "Lighting.cginc"
#include "AutoLight.cginc"
#include "UnityShaderVariables.cginc" sampler2D _MainTex;
sampler2D _Bump;
sampler2D _Ramp; float4 _MainTex_ST;
float4 _Bump_ST; float _Tooniness; struct a2v
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
float4 tangent : TANGENT;
}; struct v2f
{
float4 pos : POSITION;
float2 uv : TEXCOORD0;
float2 uv2 : TEXCOORD1;
float3 lightDirection : TEXCOORD2;
LIGHTING_COORDS(3,4)
}; v2f vert (a2v v)
{
v2f o;
//Create a rotation matrix for tangent space
TANGENT_SPACE_ROTATION;
//Store the light's direction in tangent space
o.lightDirection = mul(rotation, ObjSpaceLightDir(v.vertex));
//Transform the vertex to projection space
o.pos = mul( UNITY_MATRIX_MVP, v.vertex);
//Get the UV coordinates
o.uv = TRANSFORM_TEX (v.texcoord, _MainTex);
o.uv2 = TRANSFORM_TEX (v.texcoord, _Bump); // pass lighting information to pixel shader
TRANSFER_VERTEX_TO_FRAGMENT(o); return o;
} float4 frag(v2f i) : COLOR
{
//Get the color of the pixel from the texture
float4 c = tex2D (_MainTex, i.uv);
//Merge the colours
c.rgb = (floor(c.rgb*_Tooniness)/_Tooniness); //Get the normal from the bump map
float3 n = UnpackNormal(tex2D (_Bump, i.uv2)); //Based on the ambient light
float3 lightColor = float3(0); //Work out this distance of the light
float atten = LIGHT_ATTENUATION(i);
//Angle to the light
float diff = saturate (dot (n, normalize(i.lightDirection)));
//Perform our toon light mapping
diff = tex2D(_Ramp, float2(diff, 0.5));
//Update the colour
lightColor += _LightColor0.rgb * (diff * atten);
//Product the final color
c.rgb = lightColor * c.rgb * 2;
return c; } ENDCG
}
}
FallBack "Diffuse"
}

写在最后

上一篇里的代码我也更新过了,添加了有无法线的两种shader。和上一篇里的还有一点不一样,上一篇里的渐变纹理使用了假的双向反射分布函数,即除了漫反射方向还有视角方向进行采样。这一篇里仅仅使用了漫反射方向对渐变纹理进行采样,对应的渐变纹理也是一维的,如下:

读者有需要的可以自己添加上视角方向的采样,也就是说在v2f里添加一个新的变量viewDir,然后逐顶点计算后传递给frag函数。如果我后面有时间的话可能会回头添加上。当然,大家还是靠自己比较好。

【Unity Shader实战】卡通风格的Shader(二)的更多相关文章

  1. 【Unity Shader实战】卡通风格的Shader(一)

    写在前面 本系列其他文章: 卡通风格的Shader(二) 呜,其实很早就看到了这类Shader,实现方法很多,效果也有些许不一样.从这篇开始,陆续学习一下接触到的卡通类型Shader的编写. 本篇的最 ...

  2. 【Unity Shader】Unity Chan的卡通材质

    写在前面 时隔两个月我终于来更新博客了,之前一直在学东西,做一些项目,感觉没什么可以分享的就一直没写.本来之前打算写云彩渲染或是Compute Shader的,觉得时间比较长所以打算先写个简单的. 今 ...

  3. 关于Unity中的模型描边与Shader切换(专题二)

    模型描边 1: LOL里面的模型描边效果,点击防御塔会有描边的效果,被攻击的时候模型也要描边凸显一下2: 网上可以找到模型描边的Shader,可以直接下载使用,一组第三方的Shader, 帮我们解决了 ...

  4. Unity3d shader之卡通着色Toon Shading

    卡通着色的目的是为了让被着色物体显得过渡的不那么好,明暗交界线很明显,等等卡通风格的一系列特征, 也叫Non-photorealisticrendering非真实渲染 重点要做到两点: 1.    描 ...

  5. 【Unity Shaders】Shader学习资源和Surface Shader概述

    写在前面 写这篇文章的时候,我断断续续学习Unity Shader半年了,其实还是个门外汉.我也能体会很多童鞋那种想要学好Shader却无从下手的感觉.在这个期间,我找到一些学习Shader的教程以及 ...

  6. 【Unity Shaders】学习笔记——SurfaceShader(二)两个结构体和CG类型

    [Unity Shaders]学习笔记——SurfaceShader(二)两个结构体和CG类型 转载请注明出处:http://www.cnblogs.com/-867259206/p/5596698. ...

  7. Unity开发实战探讨-资源的加载释放最佳策略简要心得

    Unity开发实战探讨-资源的加载释放最佳策略简要心得 看过我另外一篇关于Unity资源释放随笔<Unity开发实战探讨-资源的加载释放最佳策略>如果觉得略微复杂,那么下面是一些比较简要的 ...

  8. 卡通风格的连连看ios游戏源码

    卡通风格的连连看游戏源码,该游戏是一款韩国人做的卡通风格的ios连连看游戏源码,源码设计的效果非常漂亮的,而且运行起来感觉也很好.1.游戏采用倒计时模式2.该游戏是一款社交游戏,需要通过faceboo ...

  9. 屌炸天实战 MySQL 系列教程(二) 史上最屌、你不知道的数据库操作

    此篇写MySQL中最基础,也是最重要的操作! 第一篇:屌炸天实战 MySQL 系列教程(一) 生产标准线上环境安装配置案例及棘手问题解决 第二篇:屌炸天实战 MySQL 系列教程(二) 史上最屌.你不 ...

随机推荐

  1. HDU 4501

    超市里有n件他想要的商品.小明顺便对这n件商品打了分,表示商品的实际价值.小明发现身上带了v1的人民币,会员卡里面有v2的积分,而且他能免费拿k件.他想知道他最多能买多大价值的商品. 由于小明想要的商 ...

  2. Hash算法入门指南(聊点不一样的算法人生)

    前言 很多人到现在为止都总是问我算法该怎么学啊,数据结构好难啊怎么的,学习难度被莫名的夸大了,其实不然.对于一个学计算机相关专业的人都知道,数据结构是大学的一门必修课,数据结构与算法是基础,却常常容易 ...

  3. .net带参数SQL语句的完整定义

    首先是在DAL数据访问层中的代码://数据更新的方法public static int shuxing_update(s_passnature model) { string sql = " ...

  4. Linux学习之CentOS(九)-----文件与目录的默认权限与隐藏权限

    文件与目录的默认权限与隐藏权限 一个文件有若干个属性, 包括读写运行(r, w, x)等基本权限,及是否为目录 (d) 与文件 (-) 或者是连结档 (l) 等等的属性! 要修改属性的方法在前面也约略 ...

  5. 传统方法过渡到ES6去优雅地实现JavaScript的继承

    众所周知,面向对象编程有三个重要的概念: 封装.继承.多态.而JS作为面向对象的弱类型语言,应该说是基于对象的语言,正如常说的,JS的世界里,万物皆对象.虽然JS本身不是面向对象的语言,我们可以通过模 ...

  6. --save-dev 和 --save的区别

    1. 我们在使用npm install xx --save-dev / --save安装模块或插件的时候,会将他们写入到 package.json 文件,那到底有什么区别呢? --save-dev:会 ...

  7. 模仿天猫实战【SSM版】——后台开发

    上一篇文章链接:模仿天猫实战[SSM版]--项目起步 后台需求分析 在开始码代码之前,还是需要先清楚自己要做什么事情,后台具体需要实现哪些功能: 注意: 订单.用户.订单.推荐链接均不提供增删的功能. ...

  8. Apache ActiveMQ实战(1)-基本安装配置与消息类型

    ActiveMQ简介 ActiveMQ是一种开源的,实现了JMS1.1规范的,面向消息(MOM)的中间件,为应用程序提供高效的.可扩展的.稳定的和安全的企业级消息通信.ActiveMQ使用Apache ...

  9. 好久没有写BLOG了,人老了就开始变懒了【非技术】

    算算到今天,在码农的路上已经走了15年了.马上就40不惑的我,现在是充满的疑惑.

  10. Programming In Scala笔记-第十九章、类型参数,协变逆变,上界下界

    本章主要讲Scala中的类型参数化.本章主要分成三个部分,第一部分实现一个函数式队列的数据结构,第二部分实现该结构的内部细节,最后一个部分解释其中的关键知识点.接下来的实例中将该函数式队列命名为Que ...